📄 lower.java
字号:
/* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.tools.javac.comp;import java.util.*;import com.sun.tools.javac.code.*;import com.sun.tools.javac.jvm.*;import com.sun.tools.javac.tree.*;import com.sun.tools.javac.util.*;import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;import com.sun.tools.javac.util.List;import com.sun.tools.javac.code.Symbol.*;import com.sun.tools.javac.tree.JCTree.*;import com.sun.tools.javac.code.Type.*;import com.sun.tools.javac.jvm.Target;import static com.sun.tools.javac.code.Flags.*;import static com.sun.tools.javac.code.Kinds.*;import static com.sun.tools.javac.code.TypeTags.*;import static com.sun.tools.javac.jvm.ByteCodes.*;/** This pass translates away some syntactic sugar: inner classes, * class literals, assertions, foreach loops, etc. * * <p><b>This is NOT part of any API supported by Sun Microsystems. If * you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice.</b> */public class Lower extends TreeTranslator { protected static final Context.Key<Lower> lowerKey = new Context.Key<Lower>(); public static Lower instance(Context context) { Lower instance = context.get(lowerKey); if (instance == null) instance = new Lower(context); return instance; } private Name.Table names; private Log log; private Symtab syms; private Resolve rs; private Check chk; private Attr attr; private TreeMaker make; private DiagnosticPosition make_pos; private ClassWriter writer; private ClassReader reader; private ConstFold cfolder; private Target target; private Source source; private boolean allowEnums; private final Name dollarAssertionsDisabled; private final Name classDollar; private Types types; private boolean debugLower; protected Lower(Context context) { context.put(lowerKey, this); names = Name.Table.instance(context); log = Log.instance(context); syms = Symtab.instance(context); rs = Resolve.instance(context); chk = Check.instance(context); attr = Attr.instance(context); make = TreeMaker.instance(context); writer = ClassWriter.instance(context); reader = ClassReader.instance(context); cfolder = ConstFold.instance(context); target = Target.instance(context); source = Source.instance(context); allowEnums = source.allowEnums(); dollarAssertionsDisabled = names. fromString(target.syntheticNameChar() + "assertionsDisabled"); classDollar = names. fromString("class" + target.syntheticNameChar()); types = Types.instance(context); Options options = Options.instance(context); debugLower = options.get("debuglower") != null; } /** The currently enclosing class. */ ClassSymbol currentClass; /** A queue of all translated classes. */ ListBuffer<JCTree> translated; /** Environment for symbol lookup, set by translateTopLevelClass. */ Env<AttrContext> attrEnv; /** A hash table mapping syntax trees to their ending source positions. */ Map<JCTree, Integer> endPositions;/************************************************************************** * Global mappings *************************************************************************/ /** A hash table mapping local classes to their definitions. */ Map<ClassSymbol, JCClassDecl> classdefs; /** A hash table mapping virtual accessed symbols in outer subclasses * to the actually referred symbol in superclasses. */ Map<Symbol,Symbol> actualSymbols; /** The current method definition. */ JCMethodDecl currentMethodDef; /** The current method symbol. */ MethodSymbol currentMethodSym; /** The currently enclosing outermost class definition. */ JCClassDecl outermostClassDef; /** The currently enclosing outermost member definition. */ JCTree outermostMemberDef; /** A navigator class for assembling a mapping from local class symbols * to class definition trees. * There is only one case; all other cases simply traverse down the tree. */ class ClassMap extends TreeScanner { /** All encountered class defs are entered into classdefs table. */ public void visitClassDef(JCClassDecl tree) { classdefs.put(tree.sym, tree); super.visitClassDef(tree); } } ClassMap classMap = new ClassMap(); /** Map a class symbol to its definition. * @param c The class symbol of which we want to determine the definition. */ JCClassDecl classDef(ClassSymbol c) { // First lookup the class in the classdefs table. JCClassDecl def = classdefs.get(c); if (def == null && outermostMemberDef != null) { // If this fails, traverse outermost member definition, entering all // local classes into classdefs, and try again. classMap.scan(outermostMemberDef); def = classdefs.get(c); } if (def == null) { // If this fails, traverse outermost class definition, entering all // local classes into classdefs, and try again. classMap.scan(outermostClassDef); def = classdefs.get(c); } return def; } /** A hash table mapping class symbols to lists of free variables. * accessed by them. Only free variables of the method immediately containing * a class are associated with that class. */ Map<ClassSymbol,List<VarSymbol>> freevarCache; /** A navigator class for collecting the free variables accessed * from a local class. * There is only one case; all other cases simply traverse down the tree. */ class FreeVarCollector extends TreeScanner { /** The owner of the local class. */ Symbol owner; /** The local class. */ ClassSymbol clazz; /** The list of owner's variables accessed from within the local class, * without any duplicates. */ List<VarSymbol> fvs; FreeVarCollector(ClassSymbol clazz) { this.clazz = clazz; this.owner = clazz.owner; this.fvs = List.nil(); } /** Add free variable to fvs list unless it is already there. */ private void addFreeVar(VarSymbol v) { for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail) if (l.head == v) return; fvs = fvs.prepend(v); } /** Add all free variables of class c to fvs list * unless they are already there. */ private void addFreeVars(ClassSymbol c) { List<VarSymbol> fvs = freevarCache.get(c); if (fvs != null) { for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail) { addFreeVar(l.head); } } } /** If tree refers to a variable in owner of local class, add it to * free variables list. */ public void visitIdent(JCIdent tree) { result = tree; visitSymbol(tree.sym); } // where private void visitSymbol(Symbol _sym) { Symbol sym = _sym; if (sym.kind == VAR || sym.kind == MTH) { while (sym != null && sym.owner != owner) sym = proxies.lookup(proxyName(sym.name)).sym; if (sym != null && sym.owner == owner) { VarSymbol v = (VarSymbol)sym; if (v.getConstValue() == null) { addFreeVar(v); } } else { if (outerThisStack.head != null && outerThisStack.head != _sym) visitSymbol(outerThisStack.head); } } } /** If tree refers to a class instance creation expression * add all free variables of the freshly created class. */ public void visitNewClass(JCNewClass tree) { ClassSymbol c = (ClassSymbol)tree.constructor.owner; addFreeVars(c); if (tree.encl == null && c.hasOuterInstance() && outerThisStack.head != null) visitSymbol(outerThisStack.head); super.visitNewClass(tree); } /** If tree refers to a qualified this or super expression * for anything but the current class, add the outer this * stack as a free variable. */ public void visitSelect(JCFieldAccess tree) { if ((tree.name == names._this || tree.name == names._super) && tree.selected.type.tsym != clazz && outerThisStack.head != null) visitSymbol(outerThisStack.head); super.visitSelect(tree); } /** If tree refers to a superclass constructor call, * add all free variables of the superclass. */ public void visitApply(JCMethodInvocation tree) { if (TreeInfo.name(tree.meth) == names._super) { addFreeVars((ClassSymbol) TreeInfo.symbol(tree.meth).owner); Symbol constructor = TreeInfo.symbol(tree.meth); ClassSymbol c = (ClassSymbol)constructor.owner; if (c.hasOuterInstance() && tree.meth.getTag() != JCTree.SELECT && outerThisStack.head != null) visitSymbol(outerThisStack.head); } super.visitApply(tree); } } /** Return the variables accessed from within a local class, which * are declared in the local class' owner. * (in reverse order of first access). */ List<VarSymbol> freevars(ClassSymbol c) { if ((c.owner.kind & (VAR | MTH)) != 0) { List<VarSymbol> fvs = freevarCache.get(c); if (fvs == null) { FreeVarCollector collector = new FreeVarCollector(c); collector.scan(classDef(c)); fvs = collector.fvs; freevarCache.put(c, fvs); } return fvs; } else { return List.nil(); } } Map<TypeSymbol,EnumMapping> enumSwitchMap = new LinkedHashMap<TypeSymbol,EnumMapping>(); EnumMapping mapForEnum(DiagnosticPosition pos, TypeSymbol enumClass) { EnumMapping map = enumSwitchMap.get(enumClass); if (map == null) enumSwitchMap.put(enumClass, map = new EnumMapping(pos, enumClass)); return map; } /** This map gives a translation table to be used for enum * switches. * * <p>For each enum that appears as the type of a switch * expression, we maintain an EnumMapping to assist in the * translation, as exemplified by the following example: * * <p>we translate * <pre> * switch(colorExpression) { * case red: stmt1; * case green: stmt2; * } * </pre> * into * <pre> * switch(Outer$0.$EnumMap$Color[colorExpression.ordinal()]) { * case 1: stmt1; * case 2: stmt2 * } * </pre> * with the auxilliary table intialized as follows: * <pre> * class Outer$0 { * synthetic final int[] $EnumMap$Color = new int[Color.values().length]; * static { * try { $EnumMap$Color[red.ordinal()] = 1; } catch (NoSuchFieldError ex) {} * try { $EnumMap$Color[green.ordinal()] = 2; } catch (NoSuchFieldError ex) {} * } * } * </pre> * class EnumMapping provides mapping data and support methods for this translation.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -