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

📄 jvstcodegen.java

📁 Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京技术学院的数学和计算机科学系的 Shigeru Chiba 所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * 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 javassist.*;import javassist.bytecode.*;import javassist.compiler.ast.*;/* Code generator accepting extended Java syntax for Javassist. */public class JvstCodeGen extends MemberCodeGen {    String paramArrayName = null;    String paramListName = null;    CtClass[] paramTypeList = null;    private int paramVarBase = 0;       // variable index for $0 or $1.    private boolean useParam0 = false;  // true if $0 is used.    private String param0Type = null;   // JVM name    public static final String sigName = "$sig";    public static final String dollarTypeName = "$type";    public static final String clazzName = "$class";    private CtClass dollarType = null;    CtClass returnType = null;    String returnCastName = null;    private String returnVarName = null;        // null if $_ is not used.    public static final String wrapperCastName = "$w";    String proceedName = null;    public static final String cflowName = "$cflow";    ProceedHandler procHandler = null;  // null if not used.    public JvstCodeGen(Bytecode b, CtClass cc, ClassPool cp) {        super(b, cc, cp);        setTypeChecker(new JvstTypeChecker(cc, cp, this));    }    /* Index of $1.     */    private int indexOfParam1() {        return paramVarBase + (useParam0 ? 1 : 0);    }    /* Records a ProceedHandler obejct.     *     * @param name      the name of the special method call.     *                  it is usually $proceed.     */    public void setProceedHandler(ProceedHandler h, String name) {        proceedName = name;        procHandler = h;    }    /* If the type of the expression compiled last is void,     * add ACONST_NULL and change exprType, arrayDim, className.     */    public void addNullIfVoid() {        if (exprType == VOID) {            bytecode.addOpcode(ACONST_NULL);            exprType = CLASS;            arrayDim = 0;            className = jvmJavaLangObject;        }    }    /* To support $args, $sig, and $type.     * $args is an array of parameter list.     */    public void atMember(Member mem) throws CompileError {        String name = mem.get();        if (name.equals(paramArrayName)) {            compileParameterList(bytecode, paramTypeList, indexOfParam1());            exprType = CLASS;            arrayDim = 1;            className = jvmJavaLangObject;        }        else if (name.equals(sigName)) {            bytecode.addLdc(Descriptor.ofMethod(returnType, paramTypeList));            bytecode.addInvokestatic("javassist/runtime/Desc", "getParams",                                "(Ljava/lang/String;)[Ljava/lang/Class;");            exprType = CLASS;            arrayDim = 1;            className = "java/lang/Class";        }        else if (name.equals(dollarTypeName)) {            if (dollarType == null)                throw new CompileError(dollarType + " is not available");            bytecode.addLdc(Descriptor.of(dollarType));            callGetType("getType");        }        else if (name.equals(clazzName)) {            if (param0Type == null)                throw new CompileError(clazzName + " is not available");            bytecode.addLdc(param0Type);            callGetType("getClazz");        }        else            super.atMember(mem);    }    private void callGetType(String method) {        bytecode.addInvokestatic("javassist/runtime/Desc", method,                                "(Ljava/lang/String;)Ljava/lang/Class;");        exprType = CLASS;        arrayDim = 0;        className = "java/lang/Class";    }    protected void atFieldAssign(Expr expr, int op, ASTree left,                        ASTree right, boolean doDup) throws CompileError    {        if (left instanceof Member            && ((Member)left).get().equals(paramArrayName)) {            if (op != '=')                throw new CompileError("bad operator for " + paramArrayName);            right.accept(this);            if (arrayDim != 1 || exprType != CLASS)                throw new CompileError("invalid type for " + paramArrayName);            atAssignParamList(paramTypeList, bytecode);            if (!doDup)                bytecode.addOpcode(POP);        }        else            super.atFieldAssign(expr, op, left, right, doDup);    }    protected void atAssignParamList(CtClass[] params, Bytecode code)        throws CompileError    {        if (params == null)            return;        int varNo = indexOfParam1();        int n = params.length;        for (int i = 0; i < n; ++i) {            code.addOpcode(DUP);            code.addIconst(i);            code.addOpcode(AALOAD);            compileUnwrapValue(params[i], code);            code.addStore(varNo, params[i]);            varNo += is2word(exprType, arrayDim) ? 2 : 1;        }    }    public void atCastExpr(CastExpr expr) throws CompileError {        ASTList classname = expr.getClassName();        if (classname != null && expr.getArrayDim() == 0) {            ASTree p = classname.head();            if (p instanceof Symbol && classname.tail() == null) {                String typename = ((Symbol)p).get();                if (typename.equals(returnCastName)) {                    atCastToRtype(expr);                    return;                }                else if (typename.equals(wrapperCastName)) {                    atCastToWrapper(expr);                    return;                }            }        }        super.atCastExpr(expr);    }    /**     * Inserts a cast operator to the return type.     * If the return type is void, this does nothing.     */    protected void atCastToRtype(CastExpr expr) throws CompileError {        expr.getOprand().accept(this);        if (exprType == VOID || isRefType(exprType) || arrayDim > 0)            compileUnwrapValue(returnType, bytecode);        else if (returnType instanceof CtPrimitiveType) {            CtPrimitiveType pt = (CtPrimitiveType)returnType;            int destType = MemberResolver.descToType(pt.getDescriptor());            atNumCastExpr(exprType, destType);            exprType = destType;            arrayDim = 0;            className = null;        }        else            throw new CompileError("invalid cast");    }    protected void atCastToWrapper(CastExpr expr) throws CompileError {        expr.getOprand().accept(this);        if (isRefType(exprType) || arrayDim > 0)            return;     // Object type.  do nothing.        CtClass clazz = resolver.lookupClass(exprType, arrayDim, className);        if (clazz instanceof CtPrimitiveType) {            CtPrimitiveType pt = (CtPrimitiveType)clazz;            String wrapper = pt.getWrapperName();            bytecode.addNew(wrapper);           // new <wrapper>            bytecode.addOpcode(DUP);            // dup            if (pt.getDataSize() > 1)                bytecode.addOpcode(DUP2_X2);    // dup2_x2            else                bytecode.addOpcode(DUP2_X1);    // dup2_x1            bytecode.addOpcode(POP2);           // pop2            bytecode.addInvokespecial(wrapper, "<init>",                                      "(" + pt.getDescriptor() + ")V");                                                // invokespecial            exprType = CLASS;            arrayDim = 0;            className = jvmJavaLangObject;        }    }    /* Delegates to a ProcHandler object if the method call is     * $proceed().  It may process $cflow().     */    public void atCallExpr(CallExpr expr) throws CompileError {        ASTree method = expr.oprand1();        if (method instanceof Member) {            String name = ((Member)method).get();            if (procHandler != null && name.equals(proceedName)) {                procHandler.doit(this, bytecode, (ASTList)expr.oprand2());                return;            }            else if (name.equals(cflowName)) {                atCflow((ASTList)expr.oprand2());                return;            }        }        super.atCallExpr(expr);    }    /* To support $cflow().     */    protected void atCflow(ASTList cname) throws CompileError {        StringBuffer sbuf = new StringBuffer();        if (cname == null || cname.tail() != null)            throw new CompileError("bad " + cflowName);        makeCflowName(sbuf, cname.head());        String name = sbuf.toString();        Object[] names = resolver.getClassPool().lookupCflow(name);        if (names == null)            throw new CompileError("no such a " + cflowName + ": " + name);        bytecode.addGetstatic((String)names[0], (String)names[1],                              "Ljavassist/runtime/Cflow;");        bytecode.addInvokevirtual("javassist.runtime.Cflow",                                  "value", "()I");        exprType = INT;        arrayDim = 0;        className = null;    }    /* Syntax:     *     * <cflow> : $cflow '(' <cflow name> ')'     * <cflow name> : <identifier> ('.' <identifier>)*     */    private static void makeCflowName(StringBuffer sbuf, ASTree name)        throws CompileError    {        if (name instanceof Symbol) {            sbuf.append(((Symbol)name).get());            return;        }        else if (name instanceof Expr) {            Expr expr = (Expr)name;            if (expr.getOperator() == '.') {                makeCflowName(sbuf, expr.oprand1());                sbuf.append('.');                makeCflowName(sbuf, expr.oprand2());                return;            }        }        throw new CompileError("bad " + cflowName);    }    /* To support $$.  ($$) is equivalent to ($1, ..., $n).     * It can be used only as a parameter list of method call.     */    public boolean isParamListName(ASTList args) {        if (paramTypeList != null            && args != null && args.tail() == null) {            ASTree left = args.head();            return (left instanceof Member                    && ((Member)left).get().equals(paramListName));        }        else            return false;    }    /*    public int getMethodArgsLength(ASTList args) {        if (!isParamListName(args))            return super.getMethodArgsLength(args);        return paramTypeList.length;    }    */    public int getMethodArgsLength(ASTList args) {        String pname = paramListName;        int n = 0;        while (args != null) {            ASTree a = args.head();            if (a instanceof Member && ((Member)a).get().equals(pname)) {                if (paramTypeList != null)                    n += paramTypeList.length;            }            else                ++n;            args = args.tail();        }        return n;    }    public void atMethodArgs(ASTList args, int[] types, int[] dims,                                String[] cnames) throws CompileError {        CtClass[] params = paramTypeList;        String pname = paramListName;        int i = 0;        while (args != null) {            ASTree a = args.head();            if (a instanceof Member && ((Member)a).get().equals(pname)) {                if (params != null) {                    int n = params.length;                    int regno = indexOfParam1();                    for (int k = 0; k < n; ++k) {                        CtClass p = params[k];                        regno += bytecode.addLoad(regno, p);                        setType(p);                        types[i] = exprType;                        dims[i] = arrayDim;                        cnames[i] = className;                        ++i;                    }                }            }

⌨️ 快捷键说明

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