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

📄 gen.java

📁 GJC(Generic Java Compiler)编译器
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
    /**      * Do any of the structures aborted by a non-local exit have      *  finalizers that require an empty stack?      *  @param target      The tree representing the structure that's aborted      *  @param env         The environment current at the non-local exit.      */    boolean hasFinally(Tree target, Env env) {        while (env.tree != target) {            if (env.tree.tag == Tree.TRY &&                    ((Gen.GenContext) env.info).finalize.hasFinalizer())                return true;            env = env.next;        }        return false;    }    /**      * Distribute member initializer code into constructors and <clinit>      *  method.      *  @param defs         The list of class member declarations.      *  @param c            The enclosing class.      */    List normalizeDefs(List defs, ClassSymbol c) {        ListBuffer initCode = new ListBuffer();        ListBuffer clinitCode = new ListBuffer();        ListBuffer methodDefs = new ListBuffer();        for (List l = defs; l.nonEmpty(); l = l.tail) {            Tree def = (Tree) l.head;            switch (def.tag) {            case Tree.BLOCK:                Block block = (Block) def;                if ((block.flags & STATIC) != 0)                    clinitCode.append(def);                else                    initCode.append(def);                break;            case Tree.METHODDEF:                methodDefs.append(def);                break;            case Tree.VARDEF:                VarDef vdef = (VarDef) def;                VarSymbol sym = vdef.sym;                checkDimension(vdef.pos, sym.type);                if (vdef.init != null) {                    if ((sym.flags() & STATIC) == 0) {                        Tree init = make.at(vdef.pos).Assignment(sym, vdef.init);                        initCode.append(init);                        if (endPositions != null) {                            Integer endPos = (Integer) endPositions.remove(vdef);                            if (endPos != null)                                endPositions.put(init, endPos);                        }                    } else if (sym.constValue == null) {                        Tree init = make.at(vdef.pos).Assignment(sym, vdef.init);                        clinitCode.append(init);                        if (endPositions != null) {                            Integer endPos = (Integer) endPositions.remove(vdef);                            if (endPos != null)                                endPositions.put(init, endPos);                        }                    } else {                        checkStringConstant(vdef.init.pos, sym.constValue);                    }                }                break;            default:                assert false;            }        }        if (initCode.length() != 0) {            List inits = initCode.toList();            for (Enumeration e = methodDefs.elements(); e.hasMoreElements();) {                normalizeMethod((MethodDef) e.nextElement(), inits);            }        }        if (clinitCode.length() != 0) {            MethodSymbol clinit = new MethodSymbol(STATIC, names.clinit,                    new MethodType(Type.emptyList, syms.voidType,                    Type.emptyList, syms.methodClass), c);            c.members().enter(clinit);            List clinitStats = clinitCode.toList();            Block block =                    make.at(((Tree) clinitStats.head).pos).Block(0, clinitStats);            block.endpos = TreeInfo.endPos((Tree) clinitStats.last());            methodDefs.append(make.MethodDef(clinit, block));        }        return methodDefs.toList();    }    /**      * Check a constant value and report if it is a string that is      *  too large.      */    private void checkStringConstant(int pos, Object constValue) {        if (nerrs != 0 || constValue == null || !(constValue instanceof String) ||                ((String) constValue).length() < Pool.MAX_STRING_LENGTH)            return;        log.error(pos, "limit.string");        nerrs++;    }    /**      * Insert instance initializer code into initial constructor.      *  @param md        The tree potentially representing a      *                   constructor's definition.      *  @param initCode  The list of instance initializer statements.      */    void normalizeMethod(MethodDef md, List initCode) {        if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {            List stats = md.body.stats;            ListBuffer newstats = new ListBuffer();            if (stats.nonEmpty()) {                while (TreeInfo.isSyntheticInit((Tree) stats.head)) {                    newstats.append(stats.head);                    stats = stats.tail;                }                newstats.append(stats.head);                stats = stats.tail;                while (stats.nonEmpty() &&                        TreeInfo.isSyntheticInit((Tree) stats.head)) {                    newstats.append(stats.head);                    stats = stats.tail;                }                newstats.appendList(initCode);                while (stats.nonEmpty()) {                    newstats.append(stats.head);                    stats = stats.tail;                }            }            md.body.stats = newstats.toList();            if (md.body.endpos == Position.NOPOS)                md.body.endpos = TreeInfo.endPos((Tree) md.body.stats.last());        }    }    /**      * Add abstract methods for all methods defined in one of      *  the interfaces of a given class,      *  provided they are not already implemented in the class.      *      *  @param c      The class whose interfaces are searched for methods      *                for which Miranda methods should be added.      */    void implementInterfaceMethods(ClassSymbol c) {        implementInterfaceMethods(c, c);    }    /**      * Add abstract methods for all methods defined in one of      *  the interfaces of a given class,      *  provided they are not already implemented in the class.      *      *  @param c      The class whose interfaces are searched for methods      *                for which Miranda methods should be added.      *  @param site   The class in which a definition may be needed.      */    void implementInterfaceMethods(ClassSymbol c, ClassSymbol site) {        for (List l = c.type.interfaces(); l.nonEmpty(); l = l.tail) {            ClassSymbol i = (ClassSymbol)((Type) l.head).tsym;            for (Scope.Entry e = i.members().elems; e != null; e = e.sibling) {                if (e.sym.kind == MTH && (e.sym.flags() & STATIC) == 0) {                    MethodSymbol absMeth = (MethodSymbol) e.sym;                    MethodSymbol implMeth = absMeth.binaryImplementation(site);                    if (implMeth == null)                        addAbstractMethod(site, absMeth);                    else if ((implMeth.flags() & IPROXY) != 0)                        adjustAbstractMethod(site, implMeth, absMeth);                }            }            implementInterfaceMethods(i, site);        }    }    /**      * Add an abstract methods to a class      *  which implicitly implements a method defined in some interface      *  implemented by the class. These methods are called "Miranda methods".      *  Enter the newly created method into its enclosing class scope.      *  Note that it is not entered into the class tree, as the emitter      *  doesn't need to see it there to emit an abstract method.      *      *  @param c      The class to which the Miranda method is added.      *  @param m      The interface method symbol for which a Miranda method      *                is added.      */    private void addAbstractMethod(ClassSymbol c, MethodSymbol m) {        MethodSymbol absMeth =                new MethodSymbol(m.flags() | IPROXY | SYNTHETIC, m.name, m.type, c);        c.members().enter(absMeth);    }    private void adjustAbstractMethod(ClassSymbol c, MethodSymbol pm,            MethodSymbol im) {        MethodType pmt = (MethodType) pm.type;        Type imt = c.type.memberType(im);        pmt.thrown = Check.intersect(pmt.thrown(), imt.thrown());    }    /**      * Visitor argument: The current environment.      */    Env env;    /**     * Visitor argument: The expected type (prototype).     */    Type pt;    /**     * Visitor result: The item representing the computed value.     */    Item result;    /**     * Visitor method: generate code for a definition, catching and reporting     *  any completion failures.     *  @param tree    The definition to be visited.     *  @param env     The environment current at the definition.     */    public void genDef(Tree tree, Env env) {        Env prevEnv = this.env;        try {            this.env = env;            tree.accept(this);        } catch (CompletionFailure ex) {            chk.completionError(tree.pos, ex);        }        finally { this.env = prevEnv;                } }    /**      * Derived visitor method: check whether CharacterRangeTable      *  should be emitted, if so, put a new entry into CRTable      *  and call method to generate bytecode.      *  If not, just call method to generate bytecode.      *  @see    #genStat(Tree, Env<GenContext>)      *      *  @param  tree     The tree to be visited.      *  @param  env      The environment to use.      *  @param  crtFlags The CharacterRangeTable flags      *                   indicating type of the entry.      */    public void genStat(Tree tree, Env env, int crtFlags) {        if (!genCrt) {            genStat(tree, env);            return;        }        int startpc = code.curPc();        genStat(tree, env);        if (tree.tag == Tree.BLOCK)            crtFlags |= CRT_BLOCK;        code.crt.put(tree, crtFlags, startpc, code.curPc());    }    /**      * Derived visitor method: generate code for a statement.      */    public void genStat(Tree tree, Env env) {        if (code.isAlive()) {            code.statBegin(tree.pos);            genDef(tree, env);        } else if (((Gen.GenContext) env.info).isSwitch && tree.tag == Tree.VARDEF) {            code.newLocal(((VarDef) tree).sym);        }    }    /**      * Derived visitor method: check whether CharacterRangeTable      *  should be emitted, if so, put a new entry into CRTable      *  and call method to generate bytecode.      *  If not, just call method to generate bytecode.      *  @see    #genStats(List<Trees>, Env<GenContext>)      *      *  @param  trees    The list of trees to be visited.      *  @param  env      The environment to use.      *  @param  crtFlags The CharacterRangeTable flags      *                   indicating type of the entry.      */    public void genStats(List trees, Env env, int crtFlags) {        if (!genCrt) {            genStats(trees, env);            return;        }        if (trees.length() == 1) {            genStat((Tree) trees.head, env, crtFlags | CRT_STATEMENT);        } else {            int startpc = code.curPc();            genStats(trees, env);            code.crt.put(trees, crtFlags, startpc, code.curPc());        }    }    /**      * Derived visitor method: generate code for a list of statements.      */    public void genStats(List trees, Env env) {        for (List l = trees; l.nonEmpty(); l = l.tail)            genStat((Tree) l.head, env, CRT_STATEMENT);    }    /**      * Derived visitor method: check whether CharacterRangeTable      *  should be emitted, if so, put a new entry into CRTable      *  and call method to generate bytecode.      *  If not, just call method to generate bytecode.      *  @see    #genCond(Tree)      *      *  @param  tree     The tree to be visited.      *  @param  crtFlags The CharacterRangeTable flags      *                   indicating type of the entry.      */    public CondItem genCond(Tree tree, int crtFlags) {        if (!genCrt)            return genCond(tree, false);        int startpc = code.curPc();        CondItem item = genCond(tree, (crtFlags & CRT_FLOW_CONTROLLER) != 0);        code.crt.put(tree, crtFlags, startpc, code.curPc());        return item;    }    /**      * Derived visitor method: generate code for a boolean      *  expression in a control-flow context.      *  @param tree         The expression to be visited.      *  @param markBranches The flag to indicate that the condition is      *                      a flow controller so produced conditions      *                      should contain a proper tree to generate      *                      CharacterRangeTable branches for them.      */    public CondItem genCond(Tree _tree, boolean markBranches) {        Tree inner_tree = TreeInfo.skipParens(_tree);        if (inner_tree.tag == Tree.CONDEXPR) {            Conditional tree = (Conditional) inner_tree;            CondItem cond = genCond(tree.cond, CRT_FLOW_CONTROLLER);            if (cond.isTrue()) {                code.resolve(cond.trueJumps);                CondItem result = genCond(tree.truepart, CRT_FLOW_TARGET);                if (markBranches)                    result.tree = tree.truepart;                return result;            }            if (cond.isFalse()) {                code.resolve(cond.falseJumps);                CondItem result = genCond(tree.falsepart, CRT_FLOW_TARGET);                if (markBranches)                    result.tree = tree.falsepart;                return result;            }            Chain secondJumps = cond.jumpFalse();            code.resolve(cond.trueJumps);            CondItem first = genCond(tree.truepart, CRT_FLOW_TARGET);            if (markBranches)                first.tree = tree.truepart;            Chain falseJumps = first.jumpFalse();            code.resolve(first.trueJumps);            Chain trueJumps = code.branch(goto_);            code.resolve(secondJumps);            CondItem second = genCond(tree.falsepart, CRT_FLOW_TARGET);

⌨️ 快捷键说明

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