📄 lower.java
字号:
ClassSymbol accessConstructorTag() { ClassSymbol topClass = currentClass.outermostClass(); Name flatname = names.fromString("" + topClass.getQualifiedName() + target.syntheticNameChar() + "1"); ClassSymbol ctag = chk.compiled.get(flatname); if (ctag == null) ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass); return ctag; } /** Add all required access methods for a private symbol to enclosing class. * @param sym The symbol. */ void makeAccessible(Symbol sym) { JCClassDecl cdef = classDef(sym.owner.enclClass()); assert cdef != null : "class def not found: " + sym + " in " + sym.owner; if (sym.name == names.init) { cdef.defs = cdef.defs.prepend( accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym))); } else { MethodSymbol[] accessors = accessSyms.get(sym); for (int i = 0; i < NCODES; i++) { if (accessors[i] != null) cdef.defs = cdef.defs.prepend( accessDef(cdef.pos, sym, accessors[i], i)); } } } /** Construct definition of an access method. * @param pos The source code position of the definition. * @param vsym The private or protected symbol. * @param accessor The access method for the symbol. * @param acode The access code. */ JCTree accessDef(int pos, Symbol vsym, MethodSymbol accessor, int acode) {// System.err.println("access " + vsym + " with " + accessor);//DEBUG currentClass = vsym.owner.enclClass(); make.at(pos); JCMethodDecl md = make.MethodDef(accessor, null); // Find actual symbol Symbol sym = actualSymbols.get(vsym); if (sym == null) sym = vsym; JCExpression ref; // The tree referencing the private symbol. List<JCExpression> args; // Any additional arguments to be passed along. if ((sym.flags() & STATIC) != 0) { ref = make.Ident(sym); args = make.Idents(md.params); } else { ref = make.Select(make.Ident(md.params.head), sym); args = make.Idents(md.params.tail); } JCStatement stat; // The statement accessing the private symbol. if (sym.kind == VAR) { // Normalize out all odd access codes by taking floor modulo 2: int acode1 = acode - (acode & 1); JCExpression expr; // The access method's return value. switch (acode1) { case DEREFcode: expr = ref; break; case ASSIGNcode: expr = make.Assign(ref, args.head); break; case PREINCcode: case POSTINCcode: case PREDECcode: case POSTDECcode: expr = makeUnary( ((acode1 - PREINCcode) >> 1) + JCTree.PREINC, ref); break; default: expr = make.Assignop( treeTag(binaryAccessOperator(acode1)), ref, args.head); ((JCAssignOp) expr).operator = binaryAccessOperator(acode1); } stat = make.Return(expr.setType(sym.type)); } else { stat = make.Call(make.App(ref, args)); } md.body = make.Block(0, List.of(stat)); // Make sure all parameters, result types and thrown exceptions // are accessible. for (List<JCVariableDecl> l = md.params; l.nonEmpty(); l = l.tail) l.head.vartype = access(l.head.vartype); md.restype = access(md.restype); for (List<JCExpression> l = md.thrown; l.nonEmpty(); l = l.tail) l.head = access(l.head); return md; } /** Construct definition of an access constructor. * @param pos The source code position of the definition. * @param constr The private constructor. * @param accessor The access method for the constructor. */ JCTree accessConstructorDef(int pos, Symbol constr, MethodSymbol accessor) { make.at(pos); JCMethodDecl md = make.MethodDef(accessor, accessor.externalType(types), null); JCIdent callee = make.Ident(names._this); callee.sym = constr; callee.type = constr.type; md.body = make.Block(0, List.<JCStatement>of( make.Call( make.App( callee, make.Idents(md.params.reverse().tail.reverse()))))); return md; }/************************************************************************** * Free variables proxies and this$n *************************************************************************/ /** A scope containing all free variable proxies for currently translated * class, as well as its this$n symbol (if needed). * Proxy scopes are nested in the same way classes are. * Inside a constructor, proxies and any this$n symbol are duplicated * in an additional innermost scope, where they represent the constructor * parameters. */ Scope proxies; /** A stack containing the this$n field of the currently translated * classes (if needed) in innermost first order. * Inside a constructor, proxies and any this$n symbol are duplicated * in an additional innermost scope, where they represent the constructor * parameters. */ List<VarSymbol> outerThisStack; /** The name of a free variable proxy. */ Name proxyName(Name name) { return names.fromString("val" + target.syntheticNameChar() + name); } /** Proxy definitions for all free variables in given list, in reverse order. * @param pos The source code position of the definition. * @param freevars The free variables. * @param owner The class in which the definitions go. */ List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) { long flags = FINAL | SYNTHETIC; if (owner.kind == TYP && target.usePrivateSyntheticFields()) flags |= PRIVATE; List<JCVariableDecl> defs = List.nil(); for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) { VarSymbol v = l.head; VarSymbol proxy = new VarSymbol( flags, proxyName(v.name), v.erasure(types), owner); proxies.enter(proxy); JCVariableDecl vd = make.at(pos).VarDef(proxy, null); vd.vartype = access(vd.vartype); defs = defs.prepend(vd); } return defs; } /** The name of a this$n field * @param type The class referenced by the this$n field */ Name outerThisName(Type type, Symbol owner) { Type t = type.getEnclosingType(); int nestingLevel = 0; while (t.tag == CLASS) { t = t.getEnclosingType(); nestingLevel++; } Name result = names.fromString("this" + target.syntheticNameChar() + nestingLevel); while (owner.kind == TYP && ((ClassSymbol)owner).members().lookup(result).scope != null) result = names.fromString(result.toString() + target.syntheticNameChar()); return result; } /** Definition for this$n field. * @param pos The source code position of the definition. * @param owner The class in which the definition goes. */ JCVariableDecl outerThisDef(int pos, Symbol owner) { long flags = FINAL | SYNTHETIC; if (owner.kind == TYP && target.usePrivateSyntheticFields()) flags |= PRIVATE; Type target = types.erasure(owner.enclClass().type.getEnclosingType()); VarSymbol outerThis = new VarSymbol( flags, outerThisName(target, owner), target, owner); outerThisStack = outerThisStack.prepend(outerThis); JCVariableDecl vd = make.at(pos).VarDef(outerThis, null); vd.vartype = access(vd.vartype); return vd; } /** Return a list of trees that load the free variables in given list, * in reverse order. * @param pos The source code position to be used for the trees. * @param freevars The list of free variables. */ List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) { List<JCExpression> args = List.nil(); for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) args = args.prepend(loadFreevar(pos, l.head)); return args; }//where JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) { return access(v, make.at(pos).Ident(v), null, false); } /** Construct a tree simulating the expression <C.this>. * @param pos The source code position to be used for the tree. * @param c The qualifier class. */ JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) { if (currentClass == c) { // in this case, `this' works fine return make.at(pos).This(c.erasure(types)); } else { // need to go via this$n return makeOuterThis(pos, c); } } /** Construct a tree that represents the outer instance * <C.this>. Never pick the current `this'. * @param pos The source code position to be used for the tree. * @param c The qualifier class. */ JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) { List<VarSymbol> ots = outerThisStack; if (ots.isEmpty()) { log.error(pos, "no.encl.instance.of.type.in.scope", c); assert false; return makeNull(); } VarSymbol ot = ots.head; JCExpression tree = access(make.at(pos).Ident(ot)); TypeSymbol otc = ot.type.tsym; while (otc != c) { do { ots = ots.tail; if (ots.isEmpty()) { log.error(pos, "no.encl.instance.of.type.in.scope", c); assert false; // should have been caught in Attr return tree; } ot = ots.head; } while (ot.owner != otc); if (otc.owner.kind != PCK && !otc.hasOuterInstance()) { chk.earlyRefError(pos, c); assert false; // should have been caught in Attr return makeNull(); } tree = access(make.at(pos).Select(tree, ot)); otc = ot.type.tsym; } return tree; } /** Construct a tree that represents the closest outer instance * <C.this> such that the given symbol is a member of C. * @param pos The source code position to be used for the tree. * @param sym The accessed symbol. * @param preciseMatch should we accept a type that is a subtype of * sym's owner, even if it doesn't contain sym * due to hiding, overriding, or non-inheritance * due to protection? */ JCExpression makeOwnerThis(DiagnosticPosition pos, Symbol sym, boolean preciseMatch) { Symbol c = sym.owner; if (preciseMatch ? sym.isMemberOf(currentClass, types) : currentClass.isSubClass(sym.owner, types)) { // in this case, `this' works fine return make.at(pos).This(c.erasure(types)); } else { // need to go via this$n return makeOwnerThisN(pos, sym, preciseMatch); } } /** * Similar to makeOwnerThis but will never pick "this". */ JCExpression makeOwnerThisN(DiagnosticPosition pos, Symbol sym, boolean preciseMatch) { Symbol c = sym.owner; List<VarSymbol> ots = outerThisStack; if (ots.isEmpty()) { log.error(pos, "no.encl.instance.of.type.in.scope", c); assert false; return makeNull(); } VarSymbol ot = ots.head; JCExpression tree = access(make.at(pos).Ident(ot)); TypeSymbol otc = ot.type.tsym; while (!(preciseMatch ? sym.isMemberOf(otc, types) : otc.isSubClass(sym.owner, types))) { do { ots = ots.tail; if (ots.isEmpty()) { log.error(pos, "no.encl.instance.of.type.in.scope", c); assert false; return tree; } ot = ots.head; } while (ot.owner != otc); tree = access(make.at(pos).Select(tree, ot)); otc = ot.type.tsym; } return tree; } /** Return tree simulating the assignment <this.name = name>, where * name is the name of a free variable. */ JCStatement initField(int pos, Name name) { Scope.Entry e = proxies.lookup(name); Symbol rhs = e.sym; assert rhs.owner.kind == MTH; Symbol lhs = e.next().sym; assert rhs.owner.owner == lhs.owner; make.at(pos); return make.Exec( make.Assign( make.Select(make.This(lhs.owner.erasure(types)), lhs), make.Ident(rhs)).setType(lhs.erasure(types))); } /** Return tree simulating the assignment <this.this$n = this$n>. */ JCStatement initOuterThis(int pos) { VarSymbol rhs = outerThisStack.head; assert rhs.owner.kind == MTH; VarSymbol lhs = outerThisStack.tail.head; assert rhs.owner.owner == lhs.owner; make.at(pos); return make.Exec( make.Assign( make.Select(make.This(lhs.owner.erasure(types)), lhs), make.Ident(rhs)).setType(lhs.erasure(types))); }/************************************************************************** * Code for .class *************************************************************************/ /** Return the symbol of a class to contain a cache of * compiler-generated statics such as class$ and the * $assertionsDisabled flag. We create an anonymous nested class * (unless one already exists) and return its symbol. However, * for backward compatibility in 1.4 and earlier we use the * top-level class itself. */ private ClassSymbol outerCacheClass() { ClassSymbol clazz = outermostClassDef.sym; if ((clazz.flags() & INTERFACE) == 0 && !target.useInnerCacheClass()) return clazz; Scope s = clazz.members(); for (Scope.Entry e = s.elems; e != null; e = e.sibling)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -