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

📄 gen.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
                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);
            CondItem result = items.makeCondItem(second.opcode,
                    code.mergeChains(trueJumps, second.trueJumps),
                    code.mergeChains(falseJumps, second.falseJumps));
            if (markBranches)
                result.tree = tree.falsepart;
            return result;
        } else {
            CondItem result = genExpr(_tree, syms.booleanType).mkCond();
            if (markBranches)
                result.tree = _tree;
            return result;
        }
    }

    /**
      * Visitor method: generate code for an expression, catching and reporting
      *  any completion failures.
      *  @param tree    The expression to be visited.
      *  @param pt      The expression's expected type (proto-type).
      */
    public Item genExpr(Tree tree, Type pt) {
        Type prevPt = this.pt;
        try {
            if (tree.type.constValue != null) {
                checkStringConstant(tree.pos, tree.type.constValue);
                result = items.makeImmediateItem(tree.type, tree.type.constValue);
            } else {
                this.pt = pt;
                tree.accept(this);
            }
            return result.coerce(pt);
        } catch (CompletionFailure ex) {
            chk.completionError(tree.pos, ex);
            return items.makeStackItem(pt);
        }
        finally { this.pt = prevPt;
                } }

    /**
      * Derived visitor method: generate code for a list of method arguments.
      *  @param trees    The argument expressions to be visited.
      *  @param pts      The expression's expected types (i.e. the formal parameter
      *                  types of the invoked method).
      */
    public void genArgs(List trees, List pts) {
        for (List l = trees; l.nonEmpty(); l = l.tail) {
            genExpr((Tree) l.head, (Type) pts.head).load();
            pts = pts.tail;
        }
        assert pts.isEmpty();
    }

    public void visitMethodDef(MethodDef tree) {
        Env localEnv = env.dup(tree);
        localEnv.enclMethod = tree;
        this.pt = tree.sym.erasure().restype();
        checkDimension(tree.pos, tree.sym.erasure());
        genMethod(tree, localEnv, false);
    }

    /**
      * Generate code for a method.
      *  @param tree     The tree representing the method definition.
      *  @param env      The environment current for the method body.
      *  @param fatcode  A flag that indicates whether all jumps are within 32K.
      *                  We first invoke this method under the assumption
      *                  that fatcode == false, i.e. all jumps are within 32K.
      *                  If this fails, fatcode is set to true and we try again.
      */
    void genMethod(MethodDef tree, Env env, boolean fatcode) {
        MethodSymbol meth = tree.sym;
        if (Code.width(env.enclMethod.sym.type.erasure().argtypes()) +
                (((tree.flags & STATIC) == 0 || meth.isConstructor()) ? 1 : 0) >
                ClassFile.MAX_PARAMETERS) {
            log.error(tree.pos, "limit.parameters");
            nerrs++;
        } else if (tree.body != null) {
            meth.code = code = new Code(fatcode, lineDebugInfo, varDebugInfo,
                    genCrt ? new CRTable(tree, env.toplevel.endPositions) : null);
            items = new Items(pool, code, syms);
            if (Code.debugCode)
                System.err.println(meth);
            if ((tree.flags & STATIC) == 0)
                code.setDefined( code.newLocal(
                        new VarSymbol(FINAL, names._this, meth.owner.type,
                        meth.owner)));
            for (List l = tree.params; l.nonEmpty(); l = l.tail) {
                checkDimension(((Tree.VarDef) l.head).pos,
                        ((Tree.VarDef) l.head).sym.type);
                code.setDefined(code.newLocal(((Tree.VarDef) l.head).sym));
            }
            int startpcCrt = genCrt ? code.curPc() : 0;
            genStat(tree.body, env);
            assert code.stacksize == 0;
            if (code.isAlive()) {
                code.statBegin(TreeInfo.endPos(tree.body));
                if (env.enclMethod == null ||
                        env.enclMethod.sym.type.restype().tag == VOID) {
                    code.emitop(return_);
                } else {
                    int startpc = code.entryPoint();
                    CondItem c = items.makeCondItem(goto_);
                    code.resolve(c.jumpTrue(), startpc);
                }
            }
            if (genCrt) {
                code.crt.put(tree.body, CRT_BLOCK, startpcCrt, code.curPc());
            }
            code.endScopes(0);
            if (code.checkLimits(tree.pos, log)) {
                nerrs++;
                return;
            }
            if (!fatcode && code.fatcode)
                genMethod(tree, env, true);
        }
    }

    public void visitVarDef(VarDef tree) {
        VarSymbol v = tree.sym;
        code.newLocal(v);
        if (tree.init != null) {
            checkStringConstant(tree.init.pos, v.constValue);
            if (v.constValue == null || varDebugInfo) {
                genExpr(tree.init, v.erasure()).load();
                items.makeLocalItem(v).store();
            }
        }
        checkDimension(tree.pos, v.type);
    }

    public void visitSkip(Skip tree) {
    }

    public void visitBlock(Block tree) {
        int limit = code.nextreg;
        Env localEnv = env.dup(tree, new GenContext());
        genStats(tree.stats, localEnv);
        if (env.tree.tag != Tree.METHODDEF)
            code.endScopes(limit);
    }

    public void visitDoLoop(DoLoop tree) {
        genLoop(tree, tree.body, tree.cond, Tree.emptyList, false);
    }

    public void visitWhileLoop(WhileLoop tree) {
        genLoop(tree, tree.body, tree.cond, Tree.emptyList, true);
    }

    public void visitForLoop(ForLoop tree) {
        int limit = code.nextreg;
        genStats(tree.init, env);
        genLoop(tree, tree.body, tree.cond, tree.step, true);
        code.endScopes(limit);
    }

    /**
      * Generate code for a loop.
      *  @param loop       The tree representing the loop.
      *  @param body       The loop's body.
      *  @param cond       The loop's controling condition.
      *  @param step       "Step" statements to be inserted at end of
      *                    each iteration.
      *  @param testFirst  True if the loop test belongs before the body.
      */
    private void genLoop(Tree loop, Tree body, Tree cond, List step,
            boolean testFirst) {
        Env loopEnv = env.dup(loop, new GenContext());
        int startpc = code.entryPoint();
        if (testFirst) {
            CondItem c;
            if (cond != null) {
                code.statBegin(cond.pos);
                c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
            } else {
                c = items.makeCondItem(goto_);
            }
            Chain loopDone = c.jumpFalse();
            code.resolve(c.trueJumps);
            genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
            code.resolve(((Gen.GenContext) loopEnv.info).cont);
            genStats(step, loopEnv);
            code.resolve(code.branch(goto_), startpc);
            code.resolve(loopDone);
        } else {
            genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
            code.resolve(((Gen.GenContext) loopEnv.info).cont);
            genStats(step, loopEnv);
            CondItem c;
            if (cond != null) {
                code.statBegin(cond.pos);
                c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
            } else {
                c = items.makeCondItem(goto_);
            }
            code.resolve(c.jumpTrue(), startpc);
            code.resolve(c.falseJumps);
        }
        code.resolve(((Gen.GenContext) loopEnv.info).exit);
    }

    public void visitLabelled(Labelled tree) {
        Env localEnv = env.dup(tree, new GenContext());
        genStat(tree.body, localEnv, CRT_STATEMENT);
        code.resolve(((Gen.GenContext) localEnv.info).exit);
    }

    public void visitSwitch(Switch tree) {
        int limit = code.nextreg;
        int startpcCrt = genCrt ? code.curPc() : 0;
        Item sel = genExpr(tree.selector, syms.intType);
        Bits definedSwitch = varDebugInfo ? code.defined.dup() : null;
        List cases = tree.cases;
        if (cases.isEmpty()) {
            sel.load().drop();
            if (genCrt)
                code.crt.put(TreeInfo.skipParens(tree.selector),
                        CRT_FLOW_CONTROLLER, startpcCrt, code.curPc());
        } else {
            sel.load();
            if (genCrt)
                code.crt.put(TreeInfo.skipParens(tree.selector),
                        CRT_FLOW_CONTROLLER, startpcCrt, code.curPc());
            Env switchEnv = env.dup(tree, new GenContext());
            ((Gen.GenContext) switchEnv.info).isSwitch = true;
            int lo = Integer.MAX_VALUE;
            int hi = Integer.MIN_VALUE;
            int nlabels = 0;
            int[] labels = new int[cases.length()];
            int defaultIndex = -1;
            List l = cases;
            for (int i = 0; i < labels.length; i++) {
                if (((Tree.Case) l.head).pat != null) {
                    int val = ((Number)((Tree.Case) l.head).pat.type.constValue).
                            intValue();
                    labels[i] = val;
                    if (val < lo)
                        lo = val;
                    if (hi < val)
                        hi = val;
                    nlabels++;
                } else {
                    assert defaultIndex == -1;
                    defaultIndex = i;
                }
                l = l.tail;
            }
            long table_space_cost = 4 + ((long) hi - lo + 1);
            long table_time_cost = 3;
            long lookup_space_cost = 3 + 2 * (long) nlabels;
            long lookup_time_cost = nlabels;
            int opcode = nlabels > 0 && table_space_cost + 3 * table_time_cost <=
                    lookup_space_cost + 3 * lookup_time_cost ? tableswitch :
                    lookupswitch;
            int startpc = code.curPc();
            code.emitop(opcode);
            code.align(4);
            int tableBase = code.curPc();
            int[] offsets = null;
            code.emit4(-1);
            if (opcode == tableswitch) {
                code.emit4(lo);
                code.emit4(hi);
                for (long i = lo; i <= hi; i++) {
                    code.emit4(-1);
                }
            } else {
                code.emit4(nlabels);
                for (int i = 0; i < nlabels; i++) {
                    code.emit4(-1);
                    code.emit4(-1);
                }
                offsets = new int[labels.length];
            }
            code.markDead();
            l = cases;
            for (int i = 0; i < labels.length; i++) {
                Case c = (Tree.Case) l.head;
                l = l.tail;
                int pc = code.entryPoint();
                if (i != defaultIndex) {
                    if (opcode == tableswitch) {
                        code.put4(tableBase + 4 * (labels[i] - lo + 3), pc - startpc);
                    } else {
                        offsets[i] = pc - startpc;
                    }
                } else {
                    code.put4(tableBase, pc - startpc);
                }
                code.setDefined(definedSwitch);
                genStats(c.stats, switchEnv, CRT_FLOW_TARGET);
            }
            code.resolve(((Gen.GenContext) switchEnv.info).exit);
            if (code.get4(tableBase) == -1) {
                code.put4(tableBase, code.entryPoint() - startpc);
            }
            if (opcode == tableswitch) {
                int defaultOffset = code.get4(tableBase);
                for (long i = lo; i <= hi; i++) {
                    int t = (int)(tableBase + 4 * (i - lo + 3));
                    if (code.get4(t) == -1)
                        code.put4(t, defaultOffset);
                }
            } else {
                if (defaultIndex >= 0)
                    for (int i = defaultIndex; i < labels.length - 1; i++) {
                        labels[i] = labels[i + 1];
                        offsets[i] = offsets[i + 1];
                    }
                if (nlabels > 0)
                    qsort2(labels, offsets, 0, nlabels - 1);
                for (int i = 0; i < nlabels; i++) {
                    int caseidx = tableBase + 8 * (i + 1);
                    code.put4(caseidx, labels[i]);
                    code.put4(caseidx + 4, offsets[i]);
                }
            }
        }
        code.endScopes(limit);
    }

    /**
      * Sort (int) arrays of keys and values
      */
    static void qsort2(int[] keys, int[] values, int lo, int hi) {
        int i = lo;
        int j = hi;
        int pivot = keys[(i + j) / 2];

⌨️ 快捷键说明

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