?? gen.java
字號:
/** * 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); 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);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -