?? gen.java
字號:
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]; 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(Synchronized tree) { int limit = code.nextreg; final Item lockVar = makeTemp(syms.objectType); genExpr(tree.lock, tree.lock.type).load().duplicate(); lockVar.store(); code.emitop(monitorenter); final Env syncEnv = env.dup(tree, new GenContext()); ((Gen.GenContext) syncEnv.info).finalize = new GenFinalizer() {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -