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

📄 gen.java

📁 是一款用JAVA 编写的编译器 具有很强的编译功能
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
	    int startpc = code.curPc();    // the position of the selector operation	    code.emitop0(opcode);	    code.align(4);	    int tableBase = code.curPc();  // the start of the jump table	    int[] offsets = null;          // a table of offsets for a lookupswitch	    code.emit4(-1);                // leave space for default offset	    if (opcode == tableswitch) {		code.emit4(lo);            // minimum label		code.emit4(hi);            // maximum label		for (long i = lo; i <= hi; i++) {  // leave space for jump table		    code.emit4(-1);		}	    } else {		code.emit4(nlabels);    // number of labels		for (int i = 0; i < nlabels; i++) {		    code.emit4(-1); code.emit4(-1); // leave space for lookup table		}		offsets = new int[labels.length];	    }	    Code.State stateSwitch = code.state.dup();	    code.markDead();	    // For each case do:	    l = cases;	    for (int i = 0; i < labels.length; i++) {		JCCase c = l.head;		l = l.tail;		int pc = code.entryPoint(stateSwitch);		// Insert offset directly into code or else into the		// offsets table.		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);		}		// Generate code for the statements in this case.		genStats(c.stats, switchEnv, CRT_FLOW_TARGET);	    }	    // Resolve all breaks.	    code.resolve(switchEnv.info.exit);	    // If we have not set the default offset, we do so now.	    if (code.get4(tableBase) == -1) {		code.put4(tableBase, code.entryPoint(stateSwitch) - startpc);	    }	    if (opcode == tableswitch) {		// Let any unfilled slots point to the default case.		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 {		// Sort non-default offsets and copy into lookup table.		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);    }//where	/** 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];	    do {		while (keys[i] < pivot) i++;		while (pivot < keys[j]) j--;		if (i <= j) {		    int temp1 = keys[i];		    keys[i] = keys[j];		    keys[j] = temp1;		    int temp2 = values[i];		    values[i] = values[j];		    values[j] = temp2;		    i++;		    j--;		}	    } while (i <= j);	    if (lo < j) qsort2(keys, values, lo, j);	    if (i < hi) qsort2(keys, values, i, hi);	}    public void visitSynchronized(JCSynchronized tree) {	int limit = code.nextreg;	// Generate code to evaluate lock and save in temporary variable.	final LocalItem lockVar = makeTemp(syms.objectType);	genExpr(tree.lock, tree.lock.type).load().duplicate();	lockVar.store();	// Generate code to enter monitor.	code.emitop0(monitorenter);	code.state.lock(lockVar.reg);	// Generate code for a try statement with given body, no catch clauses	// in a new environment with the "exit-monitor" operation as finalizer.	final Env<GenContext> syncEnv = env.dup(tree, new GenContext());	syncEnv.info.finalize = new GenFinalizer() {            void gen() {		genLast();	        assert syncEnv.info.gaps.length() % 2 == 0;		syncEnv.info.gaps.append(code.curPc());	    }	    void genLast() {		if (code.isAlive()) {		    lockVar.load();		    code.emitop0(monitorexit);		    code.state.unlock(lockVar.reg);		}	    }	};	syncEnv.info.gaps = new ListBuffer<Integer>();	genTry(tree.body, List.<JCCatch>nil(), syncEnv);	code.endScopes(limit);    }    public void visitTry(final JCTry tree) {	// Generate code for a try statement with given body and catch clauses,	// in a new environment which calls the finally block if there is one.	final Env<GenContext> tryEnv = env.dup(tree, new GenContext());	final Env<GenContext> oldEnv = env;        if (!useJsrLocally) {            useJsrLocally =                (stackMap == StackMapFormat.NONE) &&                (jsrlimit <= 0 ||                jsrlimit < 100 &&                estimateCodeComplexity(tree.finalizer)>jsrlimit);        }	tryEnv.info.finalize = new GenFinalizer() {	    void gen() {		if (useJsrLocally) {		    if (tree.finalizer != null) {			Code.State jsrState = code.state.dup();			jsrState.push(code.jsrReturnValue);			tryEnv.info.cont =			    new Chain(code.emitJump(jsr),				      tryEnv.info.cont,				      jsrState);		    }		    assert tryEnv.info.gaps.length() % 2 == 0;		    tryEnv.info.gaps.append(code.curPc());		} else {		    assert tryEnv.info.gaps.length() % 2 == 0;		    tryEnv.info.gaps.append(code.curPc());		    genLast();		}	    }	    void genLast() {		if (tree.finalizer != null)		    genStat(tree.finalizer, oldEnv, CRT_BLOCK);	    }	    boolean hasFinalizer() {		return tree.finalizer != null;	    }	};	tryEnv.info.gaps = new ListBuffer<Integer>();	genTry(tree.body, tree.catchers, tryEnv);    }    //where        /** Generate code for a try or synchronized statement	 *  @param body      The body of the try or synchronized statement.	 *  @param catchers  The lis of catch clauses.	 *  @param env       the environment current for the body.	 */	void genTry(JCTree body, List<JCCatch> catchers, Env<GenContext> env) {	    int limit = code.nextreg;	    int startpc = code.curPc();	    Code.State stateTry = code.state.dup();	    genStat(body, env, CRT_BLOCK);	    int endpc = code.curPc();	    boolean hasFinalizer =		env.info.finalize != null &&		env.info.finalize.hasFinalizer();	    List<Integer> gaps = env.info.gaps.toList();	    code.statBegin(TreeInfo.endPos(body));	    genFinalizer(env);	    code.statBegin(TreeInfo.endPos(env.tree));	    Chain exitChain = code.branch(goto_);	    endFinalizerGap(env);	    if (startpc != endpc) for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) {		// start off with exception on stack		code.entryPoint(stateTry, l.head.param.sym.type);		genCatch(l.head, env, startpc, endpc, gaps);		genFinalizer(env);		if (hasFinalizer || l.tail.nonEmpty()) {		    code.statBegin(TreeInfo.endPos(env.tree));		    exitChain = code.mergeChains(exitChain,						 code.branch(goto_));		}		endFinalizerGap(env);	    }	    if (hasFinalizer) {		// Create a new register segement to avoid allocating		// the same variables in finalizers and other statements.		code.newRegSegment();		// Add a catch-all clause.		// start off with exception on stack		int catchallpc = code.entryPoint(stateTry, syms.throwableType);		// Register all exception ranges for catch all clause.		// The range of the catch all clause is from the beginning		// of the try or synchronized block until the present		// code pointer excluding all gaps in the current		// environment's GenContext.		int startseg = startpc;		while (env.info.gaps.nonEmpty()) {		    int endseg = env.info.gaps.next().intValue();		    registerCatch(body.pos(), startseg, endseg,				  catchallpc, 0);		    startseg = env.info.gaps.next().intValue();		}		code.statBegin(TreeInfo.finalizerPos(env.tree));		code.markStatBegin();		Item excVar = makeTemp(syms.throwableType);		excVar.store();		genFinalizer(env);		excVar.load();		registerCatch(body.pos(), startseg,			      env.info.gaps.next().intValue(),			      catchallpc, 0);		code.emitop0(athrow);		code.markDead();		// If there are jsr's to this finalizer, ...		if (env.info.cont != null) {		    // Resolve all jsr's.		    code.resolve(env.info.cont);		    // Mark statement line number		    code.statBegin(TreeInfo.finalizerPos(env.tree));		    code.markStatBegin();		    // Save return address.		    LocalItem retVar = makeTemp(syms.throwableType);		    retVar.store();		    // Generate finalizer code.		    env.info.finalize.genLast();		    // Return.		    code.emitop1w(ret, retVar.reg);		    code.markDead();		}	    }	    // Resolve all breaks.	    code.resolve(exitChain);	    // End the scopes of all try-local variables in variable info.	    code.endScopes(limit);	}        /** Generate code for a catch clause.	 *  @param tree     The catch clause.	 *  @param env      The environment current in the enclosing try.	 *  @param startpc  Start pc of try-block.	 *  @param endpc    End pc of try-block.	 */        void genCatch(JCCatch tree,		      Env<GenContext> env,		      int startpc, int endpc,		      List<Integer> gaps) {	    if (startpc != endpc) {		int catchType = makeRef(tree.pos(), tree.param.type);		while (gaps.nonEmpty()) {		    int end = gaps.head.intValue();		    registerCatch(tree.pos(),				  startpc,  end, code.curPc(),				  catchType);		    gaps = gaps.tail;		    startpc = gaps.head.intValue();		    gaps = gaps.tail;		}		if (startpc < endpc)		    registerCatch(tree.pos(),				  startpc, endpc, code.curPc(),				  catchType);		VarSymbol exparam = tree.param.sym;		code.statBegin(tree.pos);		code.markStatBegin();		int limit = code.nextreg;		int exlocal = code.newLocal(exparam);		items.makeLocalItem(exparam).store();		code.statBegin(TreeInfo.firstStatPos(tree.body));		genStat(tree.body, env, CRT_BLOCK);		code.endScopes(limit);		code.statBegin(TreeInfo.endPos(tree.body));	    }	}        /** Register a catch clause in the "Exceptions" code-attribute.	 */	void registerCatch(DiagnosticPosition pos,			   int startpc, int endpc,			   int handler_pc, int catch_type) {    	    if (startpc != endpc) {		char startpc1 = (char)startpc;		char endpc1 = (char)endpc;		char handler_pc1 = (char)handler_pc;		if (startpc1 == startpc &&		    endpc1 == endpc &&		    handler_pc1 == handler_pc) {		    code.addCatch(startpc1, endpc1, handler_pc1,				  (char)catch_type);		} else {                    if (!useJsrLocally && !target.generateStackMapTable()) {                        useJsrLocally = true;                        throw new CodeSizeOverflow();                    } else {                        log.error(pos, "limit.code.too.large.for.try.stmt");                        nerrs++;                    }		}	    }	}    /** Very roughly estimate the number of instructions needed for     *  the given tree.     */    int estimateCodeComplexity(JCTree tree) {	if (tree == null) return 0;	class ComplexityScanner extends TreeScanner {	    int complexity = 0;	    public void scan(JCTree tree) {		if (complexity > jsrlimit) return;		super.scan(tree);	    }	    public void visitClassDef(JCClassDecl tree) {}	    public void visitDoLoop(JCDoWhileLoop tree)	        { super.visitDoLoop(tree); complexity++; }	    public void visitWhileLoop(JCWhileLoop tree)	        { super.visitWhileLoop(tree); complexity++; }	    public void visitForLoop(JCForLoop tree)	        { super.visitForLoop(tree); complexity++; }	    public void visitSwitch(JCSwitch tree)	        { super.visitSwitch(tree); complexity+=5; }	    public void visitCase(JCCase tree)	        { super.visitCase(tree); complexity++; }	    public void visitSynchronized(JCSynchronized tree)	        { super.visitSynchronized(tree); complexity+=6; }	    public void visitTry(JCTry tree)	        { super.visitTry(tree);		  if (tree.finalizer != null) complexity+=6; }	    public void visitCatch(JCCatch tree)	        { super.visitCatch(tree); complexity+=2; }	    public void visitConditional(JCConditional tree)	        { super.visitConditional(tree); complexity+=2; }	    public void visitIf(JCIf tree)	        { super.visitIf(tree); complexity+=2; }	    // note: for break, continue, and return we don't take unwind() into account.	    public void visitBreak(JCBreak tree)	        { super.visitBreak(tree); complexity+=1; }	    public void visitContinue(JCContinue tree)	        { super.visitContinue(tree); complexity+=1; }	    public void visitReturn(JCReturn tree)	        { super.visitReturn(tree); complexity+=1; }	    public void visitThrow(JCThrow tree)	        { super.visitThrow(tree); complexity+=1; }	    public void visitAssert(JCAssert tree)	        { super.visitAssert(tree); complexity+=5; }	    public void visitApply(JCMethodInvocation tree)

⌨️ 快捷键说明

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