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

📄 gen.java

📁 是一款用JAVA 编写的编译器 具有很强的编译功能
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
     *                      should contain a proper tree to generate     *                      CharacterRangeTable branches for them.     */    public CondItem genCond(JCTree _tree, boolean markBranches) {	JCTree inner_tree = TreeInfo.skipParens(_tree);	if (inner_tree.getTag() == JCTree.CONDEXPR) {	    JCConditional tree = (JCConditional)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);	    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(JCTree tree, Type pt) {	Type prevPt = this.pt;	try {	    if (tree.type.constValue() != null) {		// Short circuit any expressions which are constants		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);            code.state.stacksize = 1;	    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<JCExpression> trees, List<Type> pts) {	for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) {	    genExpr(l.head, pts.head).load();	    pts = pts.tail;	}	// require lists be of same length	assert pts.isEmpty();    }/* ************************************************************************ * Visitor methods for statements and definitions *************************************************************************/    /** Thrown when the byte code size exceeds limit.     */    public static class CodeSizeOverflow extends RuntimeException {        private static final long serialVersionUID = 0;        public CodeSizeOverflow() {}    }        public void visitMethodDef(JCMethodDecl tree) {	// Create a new local environment that points pack at method	// definition.	Env<GenContext> localEnv = env.dup(tree);	localEnv.enclMethod = tree;	// The expected type of every return statement in this method	// is the method's return type.	this.pt = tree.sym.erasure(types).getReturnType();	checkDimension(tree.pos(), tree.sym.erasure(types));	genMethod(tree, localEnv, false);    }//where        /** 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(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {	    MethodSymbol meth = tree.sym;//    	System.err.println("Generating " + meth + " in " + meth.owner); //DEBUG	    if (Code.width(types.erasure(env.enclMethod.sym.type).getParameterTypes())  +		(((tree.mods.flags & STATIC) == 0 || meth.isConstructor()) ? 1 : 0) >		ClassFile.MAX_PARAMETERS) {		log.error(tree.pos(), "limit.parameters");		nerrs++;	    }	    else if (tree.body != null) {		// Create a new code structure and initialize it.                int startpcCrt = initCode(tree, env, fatcode);		try {                    genStat(tree.body, env);                } catch (CodeSizeOverflow e) {                    // Failed due to code limit, try again with jsr/ret                    startpcCrt = initCode(tree, env, fatcode);                    genStat(tree.body, env);                }                		if (code.state.stacksize != 0) {		    log.error(tree.body.pos(), "stack.sim.error", tree);		    throw new AssertionError();		}		// If last statement could complete normally, insert a		// return at the end.		if (code.isAlive()) {		    code.statBegin(TreeInfo.endPos(tree.body));		    if (env.enclMethod == null ||			env.enclMethod.sym.type.getReturnType().tag == VOID) {			code.emitop0(return_);		    } else {			// sometime dead code seems alive (4415991);			// generate a small loop instead			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());		// End the scope of all local variables in variable info.		code.endScopes(0);		// If we exceeded limits, panic		if (code.checkLimits(tree.pos(), log)) {		    nerrs++;		    return;		}		// If we generated short code but got a long jump, do it again		// with fatCode = true.		if (!fatcode && code.fatcode) genMethod(tree, env, true);		// Clean up		if(stackMap == StackMapFormat.JSR202) {		    code.lastFrame = null;		    code.frameBeforeLast = null;		}	    }	}        private int initCode(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {            MethodSymbol meth = tree.sym;                        // Create a new code structure.            meth.code = code = new Code(meth,                                        fatcode,                                         lineDebugInfo ? toplevel.lineMap : null,                                         varDebugInfo,                                        stackMap,                                         debugCode,                                        genCrt ? new CRTable(tree, env.toplevel.endPositions)                                                : null,                                        syms,                                        types,                                        pool);            items = new Items(pool, code, syms, types);            if (code.debugCode)                System.err.println(meth + " for body " + tree);            // If method is not static, create a new local variable address            // for `this'.            if ((tree.mods.flags & STATIC) == 0) {                Type selfType = meth.owner.type;                if (meth.isConstructor() && selfType != syms.objectType)                    selfType = UninitializedType.uninitializedThis(selfType);                code.setDefined(                        code.newLocal(                            new VarSymbol(FINAL, names._this, selfType, meth.owner)));            }            // Mark all parameters as defined from the beginning of            // the method.            for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {                checkDimension(l.head.pos(), l.head.sym.type);                code.setDefined(code.newLocal(l.head.sym));            }            // Get ready to generate code for method body.            int startpcCrt = genCrt ? code.curPc() : 0;            code.entryPoint();            // Suppress initial stackmap            code.pendingStackMap = false;                            return startpcCrt;        }            public void visitVarDef(JCVariableDecl tree) {	VarSymbol v = tree.sym;	code.newLocal(v);	if (tree.init != null) {	    checkStringConstant(tree.init.pos(), v.getConstValue());	    if (v.getConstValue() == null || varDebugInfo) {		genExpr(tree.init, v.erasure(types)).load();		items.makeLocalItem(v).store();	    }	}	checkDimension(tree.pos(), v.type);    }    public void visitSkip(JCSkip tree) {    }    public void visitBlock(JCBlock tree) {	int limit = code.nextreg;	Env<GenContext> localEnv = env.dup(tree, new GenContext());	genStats(tree.stats, localEnv);	// End the scope of all block-local variables in variable info.	if (env.tree.getTag() != JCTree.METHODDEF) {            code.statBegin(tree.endpos);            code.endScopes(limit);            code.pendingStatPos = Position.NOPOS;        }    }    public void visitDoLoop(JCDoWhileLoop tree) {	genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), false);    }    public void visitWhileLoop(JCWhileLoop tree) {	genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), true);    }    public void visitForLoop(JCForLoop tree) {	int limit = code.nextreg;	genStats(tree.init, env);	genLoop(tree, tree.body, tree.cond, tree.step, true);	code.endScopes(limit);    }    //where        /** 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(JCStatement loop,			     JCStatement body,			     JCExpression cond,			     List<JCExpressionStatement> step,			     boolean testFirst) {	    Env<GenContext> 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(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(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(loopEnv.info.exit);	}    public void visitForeachLoop(JCEnhancedForLoop tree) {	throw new AssertionError(); // should have been removed by Lower.    }    public void visitLabelled(JCLabeledStatement tree) {	Env<GenContext> localEnv = env.dup(tree, new GenContext());	genStat(tree.body, localEnv, CRT_STATEMENT);	code.resolve(localEnv.info.exit);    }    public void visitSwitch(JCSwitch tree) {	int limit = code.nextreg;	assert tree.selector.type.tag != CLASS;	int startpcCrt = genCrt ? code.curPc() : 0;	Item sel = genExpr(tree.selector, syms.intType);	List<JCCase> cases = tree.cases;	if (cases.isEmpty()) {	    // We are seeing:  switch <sel> {}	    sel.load().drop();	    if (genCrt)		code.crt.put(TreeInfo.skipParens(tree.selector),			     CRT_FLOW_CONTROLLER, startpcCrt, code.curPc());	} else {	    // We are seeing a nonempty switch.	    sel.load();	    if (genCrt)		code.crt.put(TreeInfo.skipParens(tree.selector),			     CRT_FLOW_CONTROLLER, startpcCrt, code.curPc());	    Env<GenContext> switchEnv = env.dup(tree, new GenContext());	    switchEnv.info.isSwitch = true;	    // Compute number of labels and minimum and maximum label values.	    // For each case, store its label in an array.	    int lo = Integer.MAX_VALUE;  // minimum label.	    int hi = Integer.MIN_VALUE;  // maximum label.	    int nlabels = 0;               // number of labels.	    int[] labels = new int[cases.length()];  // the label array.	    int defaultIndex = -1;     // the index of the default clause.	    List<JCCase> l = cases;	    for (int i = 0; i < labels.length; i++) {		if (l.head.pat != null) {		    int val = ((Number)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;	    }	    // Determine whether to issue a tableswitch or a lookupswitch	    // instruction.	    long table_space_cost = 4 + ((long) hi - lo + 1); // words	    long table_time_cost = 3; // comparisons	    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;

⌨️ 快捷键说明

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