📄 lower.java
字号:
for (Scope.Entry e = syms.predefClass.members().elems; e != null; e = e.sibling) { if (e.sym instanceof OperatorSymbol) { OperatorSymbol op = (OperatorSymbol)e.sym; if (accessCode(op.opcode) == acode) return op; } } return null; } /** Return tree tag for assignment operation corresponding * to given binary operator. */ private static int treeTag(OperatorSymbol operator) { switch (operator.opcode) { case ByteCodes.ior: case ByteCodes.lor: return JCTree.BITOR_ASG; case ByteCodes.ixor: case ByteCodes.lxor: return JCTree.BITXOR_ASG; case ByteCodes.iand: case ByteCodes.land: return JCTree.BITAND_ASG; case ByteCodes.ishl: case ByteCodes.lshl: case ByteCodes.ishll: case ByteCodes.lshll: return JCTree.SL_ASG; case ByteCodes.ishr: case ByteCodes.lshr: case ByteCodes.ishrl: case ByteCodes.lshrl: return JCTree.SR_ASG; case ByteCodes.iushr: case ByteCodes.lushr: case ByteCodes.iushrl: case ByteCodes.lushrl: return JCTree.USR_ASG; case ByteCodes.iadd: case ByteCodes.ladd: case ByteCodes.fadd: case ByteCodes.dadd: case ByteCodes.string_add: return JCTree.PLUS_ASG; case ByteCodes.isub: case ByteCodes.lsub: case ByteCodes.fsub: case ByteCodes.dsub: return JCTree.MINUS_ASG; case ByteCodes.imul: case ByteCodes.lmul: case ByteCodes.fmul: case ByteCodes.dmul: return JCTree.MUL_ASG; case ByteCodes.idiv: case ByteCodes.ldiv: case ByteCodes.fdiv: case ByteCodes.ddiv: return JCTree.DIV_ASG; case ByteCodes.imod: case ByteCodes.lmod: case ByteCodes.fmod: case ByteCodes.dmod: return JCTree.MOD_ASG; default: throw new AssertionError(); } } /** The name of the access method with number `anum' and access code `acode'. */ Name accessName(int anum, int acode) { return names.fromString( "access" + target.syntheticNameChar() + anum + acode / 10 + acode % 10); } /** Return access symbol for a private or protected symbol from an inner class. * @param sym The accessed private symbol. * @param tree The accessing tree. * @param enclOp The closest enclosing operation node of tree, * null if tree is not a subtree of an operation. * @param protAccess Is access to a protected symbol in another * package? * @param refSuper Is access via a (qualified) C.super? */ MethodSymbol accessSymbol(Symbol sym, JCTree tree, JCTree enclOp, boolean protAccess, boolean refSuper) { ClassSymbol accOwner = refSuper && protAccess // For access via qualified super (T.super.x), place the // access symbol on T. ? (ClassSymbol)((JCFieldAccess) tree).selected.type.tsym // Otherwise pretend that the owner of an accessed // protected symbol is the enclosing class of the current // class which is a subclass of the symbol's owner. : accessClass(sym, protAccess, tree); Symbol vsym = sym; if (sym.owner != accOwner) { vsym = sym.clone(accOwner); actualSymbols.put(vsym, sym); } Integer anum // The access number of the access method. = accessNums.get(vsym); if (anum == null) { anum = accessed.length(); accessNums.put(vsym, anum); accessSyms.put(vsym, new MethodSymbol[NCODES]); accessed.append(vsym); // System.out.println("accessing " + vsym + " in " + vsym.location()); } int acode; // The access code of the access method. List<Type> argtypes; // The argument types of the access method. Type restype; // The result type of the access method. List<Type> thrown; // The thrown execeptions of the access method. switch (vsym.kind) { case VAR: acode = accessCode(tree, enclOp); if (acode >= FIRSTASGOPcode) { OperatorSymbol operator = binaryAccessOperator(acode); if (operator.opcode == string_add) argtypes = List.of(syms.objectType); else argtypes = operator.type.getParameterTypes().tail; } else if (acode == ASSIGNcode) argtypes = List.of(vsym.erasure(types)); else argtypes = List.nil(); restype = vsym.erasure(types); thrown = List.nil(); break; case MTH: acode = DEREFcode; argtypes = vsym.erasure(types).getParameterTypes(); restype = vsym.erasure(types).getReturnType(); thrown = vsym.type.getThrownTypes(); break; default: throw new AssertionError(); } // For references via qualified super, increment acode by one, // making it odd. if (protAccess && refSuper) acode++; // Instance access methods get instance as first parameter. // For protected symbols this needs to be the instance as a member // of the type containing the accessed symbol, not the class // containing the access method. if ((vsym.flags() & STATIC) == 0) { argtypes = argtypes.prepend(vsym.owner.erasure(types)); } MethodSymbol[] accessors = accessSyms.get(vsym); MethodSymbol accessor = accessors[acode]; if (accessor == null) { accessor = new MethodSymbol( STATIC | SYNTHETIC, accessName(anum.intValue(), acode), new MethodType(argtypes, restype, thrown, syms.methodClass), accOwner); enterSynthetic(tree.pos(), accessor, accOwner.members()); accessors[acode] = accessor; } return accessor; } /** The qualifier to be used for accessing a symbol in an outer class. * This is either C.sym or C.this.sym, depending on whether or not * sym is static. * @param sym The accessed symbol. */ JCExpression accessBase(DiagnosticPosition pos, Symbol sym) { return (sym.flags() & STATIC) != 0 ? access(make.at(pos.getStartPosition()).QualIdent(sym.owner)) : makeOwnerThis(pos, sym, true); } /** Do we need an access method to reference private symbol? */ boolean needsPrivateAccess(Symbol sym) { if ((sym.flags() & PRIVATE) == 0 || sym.owner == currentClass) { return false; } else if (sym.name == names.init && (sym.owner.owner.kind & (VAR | MTH)) != 0) { // private constructor in local class: relax protection sym.flags_field &= ~PRIVATE; return false; } else { return true; } } /** Do we need an access method to reference symbol in other package? */ boolean needsProtectedAccess(Symbol sym, JCTree tree) { if ((sym.flags() & PROTECTED) == 0 || sym.owner.owner == currentClass.owner || // fast special case sym.packge() == currentClass.packge()) return false; if (!currentClass.isSubClass(sym.owner, types)) return true; if ((sym.flags() & STATIC) != 0 || tree.getTag() != JCTree.SELECT || TreeInfo.name(((JCFieldAccess) tree).selected) == names._super) return false; return !((JCFieldAccess) tree).selected.type.tsym.isSubClass(currentClass, types); } /** The class in which an access method for given symbol goes. * @param sym The access symbol * @param protAccess Is access to a protected symbol in another * package? */ ClassSymbol accessClass(Symbol sym, boolean protAccess, JCTree tree) { if (protAccess) { Symbol qualifier = null; ClassSymbol c = currentClass; if (tree.getTag() == JCTree.SELECT && (sym.flags() & STATIC) == 0) { qualifier = ((JCFieldAccess) tree).selected.type.tsym; while (!qualifier.isSubClass(c, types)) { c = c.owner.enclClass(); } return c; } else { while (!c.isSubClass(sym.owner, types)) { c = c.owner.enclClass(); } } return c; } else { // the symbol is private return sym.owner.enclClass(); } } /** Ensure that identifier is accessible, return tree accessing the identifier. * @param sym The accessed symbol. * @param tree The tree referring to the symbol. * @param enclOp The closest enclosing operation node of tree, * null if tree is not a subtree of an operation. * @param refSuper Is access via a (qualified) C.super? */ JCExpression access(Symbol sym, JCExpression tree, JCExpression enclOp, boolean refSuper) { // Access a free variable via its proxy, or its proxy's proxy while (sym.kind == VAR && sym.owner.kind == MTH && sym.owner.enclClass() != currentClass) { // A constant is replaced by its constant value. Object cv = ((VarSymbol)sym).getConstValue(); if (cv != null) { make.at(tree.pos); return makeLit(sym.type, cv); } // Otherwise replace the variable by its proxy. sym = proxies.lookup(proxyName(sym.name)).sym; assert sym != null && (sym.flags_field & FINAL) != 0; tree = make.at(tree.pos).Ident(sym); } JCExpression base = (tree.getTag() == JCTree.SELECT) ? ((JCFieldAccess) tree).selected : null; switch (sym.kind) { case TYP: if (sym.owner.kind != PCK) { // Convert type idents to // <flat name> or <package name> . <flat name> Name flatname = Convert.shortName(sym.flatName()); while (base != null && TreeInfo.symbol(base) != null && TreeInfo.symbol(base).kind != PCK) { base = (base.getTag() == JCTree.SELECT) ? ((JCFieldAccess) base).selected : null; } if (tree.getTag() == JCTree.IDENT) { ((JCIdent) tree).name = flatname; } else if (base == null) { tree = make.at(tree.pos).Ident(sym); ((JCIdent) tree).name = flatname; } else { ((JCFieldAccess) tree).selected = base; ((JCFieldAccess) tree).name = flatname; } } break; case MTH: case VAR: if (sym.owner.kind == TYP) { // Access methods are required for // - private members, // - protected members in a superclass of an // enclosing class contained in another package. // - all non-private members accessed via a qualified super. boolean protAccess = refSuper && !needsPrivateAccess(sym) || needsProtectedAccess(sym, tree); boolean accReq = protAccess || needsPrivateAccess(sym); // A base has to be supplied for // - simple identifiers accessing variables in outer classes. boolean baseReq = base == null && sym.owner != syms.predefClass && !sym.isMemberOf(currentClass, types); if (accReq || baseReq) { make.at(tree.pos); // Constants are replaced by their constant value. if (sym.kind == VAR) { Object cv = ((VarSymbol)sym).getConstValue(); if (cv != null) return makeLit(sym.type, cv); } // Private variables and methods are replaced by calls // to their access methods. if (accReq) { List<JCExpression> args = List.nil(); if ((sym.flags() & STATIC) == 0) { // Instance access methods get instance // as first parameter. if (base == null) base = makeOwnerThis(tree.pos(), sym, true); args = args.prepend(base); base = null; // so we don't duplicate code } Symbol access = accessSymbol(sym, tree, enclOp, protAccess, refSuper); JCExpression receiver = make.Select( base != null ? base : make.QualIdent(access.owner), access); return make.App(receiver, args); // Other accesses to members of outer classes get a // qualifier. } else if (baseReq) { return make.at(tree.pos).Select( accessBase(tree.pos(), sym), sym).setType(tree.type); } } } } return tree; } /** Ensure that identifier is accessible, return tree accessing the identifier. * @param tree The identifier tree. */ JCExpression access(JCExpression tree) { Symbol sym = TreeInfo.symbol(tree); return sym == null ? tree : access(sym, tree, null, false); } /** Return access constructor for a private constructor, * or the constructor itself, if no access constructor is needed. * @param pos The position to report diagnostics, if any. * @param constr The private constructor. */ Symbol accessConstructor(DiagnosticPosition pos, Symbol constr) { if (needsPrivateAccess(constr)) { ClassSymbol accOwner = constr.owner.enclClass(); MethodSymbol aconstr = accessConstrs.get(constr); if (aconstr == null) { List<Type> argtypes = constr.type.getParameterTypes(); if ((accOwner.flags_field & ENUM) != 0) argtypes = argtypes .prepend(syms.intType) .prepend(syms.stringType); aconstr = new MethodSymbol( SYNTHETIC, names.init, new MethodType( argtypes.append( accessConstructorTag().erasure(types)), constr.type.getReturnType(), constr.type.getThrownTypes(), syms.methodClass), accOwner); enterSynthetic(pos, aconstr, accOwner.members()); accessConstrs.put(constr, aconstr); accessed.append(constr); } return aconstr; } else { return constr; } } /** Return an anonymous class nested in this toplevel class. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -