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

📄 gen.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
      *  @param to      the least deeply nested environment to mark
      */
    void endFinalizerGaps(Env from, Env to) {
        Env last = null;
        while (last != to) {
            endFinalizerGap(from);
            last = from;
            from = from.next;
        }
    }

    /**
      * 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);

⌨️ 快捷键说明

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