< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java

Print this page




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.comp;
  27 


  28 import java.util.*;
  29 import java.util.Map.Entry;
  30 import java.util.function.Function;
  31 import java.util.stream.Stream;

  32 
  33 import com.sun.source.tree.CaseTree.CaseKind;
  34 import com.sun.tools.javac.code.*;
  35 import com.sun.tools.javac.code.Kinds.KindSelector;
  36 import com.sun.tools.javac.code.Scope.WriteableScope;

  37 import com.sun.tools.javac.jvm.*;
  38 import com.sun.tools.javac.main.Option.PkgInfo;
  39 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  40 import com.sun.tools.javac.tree.*;
  41 import com.sun.tools.javac.util.*;
  42 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  43 import com.sun.tools.javac.util.List;
  44 
  45 import com.sun.tools.javac.code.Symbol.*;
  46 import com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode;
  47 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  48 import com.sun.tools.javac.tree.JCTree.*;
  49 import com.sun.tools.javac.code.Type.*;
  50 
  51 import com.sun.tools.javac.jvm.Target;
  52 import com.sun.tools.javac.tree.EndPosTable;
  53 
  54 import static com.sun.tools.javac.code.Flags.*;
  55 import static com.sun.tools.javac.code.Flags.BLOCK;
  56 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  57 import static com.sun.tools.javac.code.TypeTag.*;
  58 import static com.sun.tools.javac.code.Kinds.Kind.*;
  59 import static com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode.DEREF;
  60 import static com.sun.tools.javac.jvm.ByteCodes.*;
  61 import com.sun.tools.javac.tree.JCTree.JCBreak;
  62 import com.sun.tools.javac.tree.JCTree.JCCase;
  63 import com.sun.tools.javac.tree.JCTree.JCExpression;
  64 import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
  65 import static com.sun.tools.javac.tree.JCTree.JCOperatorExpression.OperandPos.LEFT;
  66 import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
  67 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  68 
  69 /** This pass translates away some syntactic sugar: inner classes,
  70  *  class literals, assertions, foreach loops, etc.
  71  *
  72  *  <p><b>This is NOT part of any supported API.
  73  *  If you write code that depends on this, you do so at your own risk.
  74  *  This code and its internal interfaces are subject to change or
  75  *  deletion without notice.</b>
  76  */
  77 public class Lower extends TreeTranslator {
  78     protected static final Context.Key<Lower> lowerKey = new Context.Key<>();
  79 
  80     public static Lower instance(Context context) {
  81         Lower instance = context.get(lowerKey);
  82         if (instance == null)
  83             instance = new Lower(context);
  84         return instance;


 788                 log.error(pos, Errors.CannotGenerateClass(sym.location(), Fragments.SyntheticNameConflict(sym, sym.location())));
 789             }
 790         }
 791     };
 792 
 793     /** Look up a synthetic name in a given scope.
 794      *  @param s            The scope.
 795      *  @param name         The name.
 796      */
 797     private Symbol lookupSynthetic(Name name, Scope s) {
 798         Symbol sym = s.findFirst(name);
 799         return (sym==null || (sym.flags()&SYNTHETIC)==0) ? null : sym;
 800     }
 801 
 802     /** Look up a method in a given scope.
 803      */
 804     private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
 805         return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
 806     }
 807 















 808     /** Anon inner classes are used as access constructor tags.
 809      * accessConstructorTag will use an existing anon class if one is available,
 810      * and synthethise a class (with makeEmptyClass) if one is not available.
 811      * However, there is a small possibility that an existing class will not
 812      * be generated as expected if it is inside a conditional with a constant
 813      * expression. If that is found to be the case, create an empty class tree here.
 814      */
 815     private void checkAccessConstructorTags() {
 816         for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
 817             ClassSymbol c = l.head;
 818             if (isTranslatedClassAvailable(c))
 819                 continue;
 820             // Create class definition tree.
 821             JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
 822                     c.outermostClass(), c.flatname, false);
 823             swapAccessConstructorTag(c, cdec.sym);
 824             translated.append(cdec);
 825         }
 826     }
 827     // where


2174         ClassSymbol currentClassPrev = currentClass;
2175         MethodSymbol currentMethodSymPrev = currentMethodSym;
2176 
2177         currentClass = tree.sym;
2178         currentMethodSym = null;
2179         attrEnv = typeEnvs.remove(currentClass);
2180         if (attrEnv == null)
2181             attrEnv = prevEnv;
2182 
2183         classdefs.put(currentClass, tree);
2184 
2185         Map<Symbol, Symbol> prevProxies = proxies;
2186         proxies = new HashMap<>(proxies);
2187         List<VarSymbol> prevOuterThisStack = outerThisStack;
2188 
2189         // If this is an enum definition
2190         if ((tree.mods.flags & ENUM) != 0 &&
2191             (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2192             visitEnumDef(tree);
2193 




2194         // If this is a nested class, define a this$n field for
2195         // it and add to proxies.
2196         JCVariableDecl otdef = null;
2197         if (currentClass.hasOuterInstance())
2198             otdef = outerThisDef(tree.pos, currentClass);
2199 
2200         // If this is a local class, define proxies for all its free variables.
2201         List<JCVariableDecl> fvdefs = freevarDefs(
2202             tree.pos, freevars(currentClass), currentClass);
2203 
2204         // Recursively translate superclass, interfaces.
2205         tree.extending = translate(tree.extending);
2206         tree.implementing = translate(tree.implementing);
2207 
2208         if (currentClass.isLocal()) {
2209             ClassSymbol encl = currentClass.owner.enclClass();
2210             if (encl.trans_local == null) {
2211                 encl.trans_local = List.nil();
2212             }
2213             encl.trans_local = encl.trans_local.prepend(currentClass);


2243         }
2244         if (currentClass.hasOuterInstance()) {
2245             tree.defs = tree.defs.prepend(otdef);
2246             enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
2247         }
2248 
2249         proxies = prevProxies;
2250         outerThisStack = prevOuterThisStack;
2251 
2252         // Append translated tree to `translated' queue.
2253         translated.append(tree);
2254 
2255         attrEnv = prevEnv;
2256         currentClass = currentClassPrev;
2257         currentMethodSym = currentMethodSymPrev;
2258 
2259         // Return empty block {} as a placeholder for an inner class.
2260         result = make_at(tree.pos()).Block(SYNTHETIC, List.nil());
2261     }
2262 































2263     /** Translate an enum class. */
2264     private void visitEnumDef(JCClassDecl tree) {
2265         make_at(tree.pos());
2266 
2267         // add the supertype, if needed
2268         if (tree.extending == null)
2269             tree.extending = make.Type(types.supertype(tree.type));
2270 
2271         // classOfType adds a cache field to tree.defs
2272         JCExpression e_class = classOfType(tree.sym.type, tree.pos()).
2273             setType(types.erasure(syms.classType));
2274 
2275         // process each enumeration constant, adding implicit constructor parameters
2276         int nextOrdinal = 0;
2277         ListBuffer<JCExpression> values = new ListBuffer<>();
2278         ListBuffer<JCTree> enumDefs = new ListBuffer<>();
2279         ListBuffer<JCTree> otherDefs = new ListBuffer<>();
2280         for (List<JCTree> defs = tree.defs;
2281              defs.nonEmpty();
2282              defs=defs.tail) {


2396         enumDefs.appendList(otherDefs.toList());
2397         tree.defs = enumDefs.toList();
2398     }
2399         // where
2400         private MethodSymbol systemArraycopyMethod;
2401         private boolean useClone() {
2402             try {
2403                 return syms.objectType.tsym.members().findFirst(names.clone) != null;
2404             }
2405             catch (CompletionFailure e) {
2406                 return false;
2407             }
2408         }
2409 
2410     /** Translate an enumeration constant and its initializer. */
2411     private void visitEnumConstantDef(JCVariableDecl var, int ordinal) {
2412         JCNewClass varDef = (JCNewClass)var.init;
2413         varDef.args = varDef.args.
2414             prepend(makeLit(syms.intType, ordinal)).
2415             prepend(makeLit(syms.stringType, var.name.toString()));





































































































































































































































































2416     }
2417 
2418     public void visitMethodDef(JCMethodDecl tree) {
2419         if (tree.name == names.init && (currentClass.flags_field&ENUM) != 0) {
2420             // Add "String $enum$name, int $enum$ordinal" to the beginning of the
2421             // argument list for each constructor of an enum.
2422             JCVariableDecl nameParam = make_at(tree.pos()).
2423                 Param(names.fromString(target.syntheticNameChar() +
2424                                        "enum" + target.syntheticNameChar() + "name"),
2425                       syms.stringType, tree.sym);
2426             nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC;
2427             JCVariableDecl ordParam = make.
2428                 Param(names.fromString(target.syntheticNameChar() +
2429                                        "enum" + target.syntheticNameChar() +
2430                                        "ordinal"),
2431                       syms.intType, tree.sym);
2432             ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC;
2433 
2434             MethodSymbol m = tree.sym;
2435             tree.params = tree.params.prepend(ordParam).prepend(nameParam);




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import sun.invoke.util.BytecodeName;
  29 
  30 import java.util.*;
  31 import java.util.Map.Entry;
  32 import java.util.function.Function;
  33 import java.util.stream.Stream;
  34 import java.util.stream.Collectors;
  35 
  36 import com.sun.source.tree.CaseTree.CaseKind;
  37 import com.sun.tools.javac.code.*;
  38 import com.sun.tools.javac.code.Kinds.KindSelector;
  39 import com.sun.tools.javac.code.Scope.WriteableScope;
  40 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext;
  41 import com.sun.tools.javac.jvm.*;
  42 import com.sun.tools.javac.main.Option.PkgInfo;
  43 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  44 import com.sun.tools.javac.tree.*;
  45 import com.sun.tools.javac.util.*;
  46 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  47 import com.sun.tools.javac.util.List;
  48 
  49 import com.sun.tools.javac.code.Symbol.*;
  50 import com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode;
  51 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  52 import com.sun.tools.javac.tree.JCTree.*;
  53 import com.sun.tools.javac.code.Type.*;
  54 
  55 import com.sun.tools.javac.jvm.Target;
  56 import com.sun.tools.javac.tree.EndPosTable;
  57 
  58 import static com.sun.tools.javac.code.Flags.*;
  59 import static com.sun.tools.javac.code.Flags.BLOCK;
  60 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  61 import static com.sun.tools.javac.code.TypeTag.*;
  62 import static com.sun.tools.javac.code.Kinds.Kind.*;
  63 import static com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode.DEREF;
  64 import static com.sun.tools.javac.jvm.ByteCodes.*;




  65 import static com.sun.tools.javac.tree.JCTree.JCOperatorExpression.OperandPos.LEFT;
  66 import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
  67 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  68 
  69 /** This pass translates away some syntactic sugar: inner classes,
  70  *  class literals, assertions, foreach loops, etc.
  71  *
  72  *  <p><b>This is NOT part of any supported API.
  73  *  If you write code that depends on this, you do so at your own risk.
  74  *  This code and its internal interfaces are subject to change or
  75  *  deletion without notice.</b>
  76  */
  77 public class Lower extends TreeTranslator {
  78     protected static final Context.Key<Lower> lowerKey = new Context.Key<>();
  79 
  80     public static Lower instance(Context context) {
  81         Lower instance = context.get(lowerKey);
  82         if (instance == null)
  83             instance = new Lower(context);
  84         return instance;


 788                 log.error(pos, Errors.CannotGenerateClass(sym.location(), Fragments.SyntheticNameConflict(sym, sym.location())));
 789             }
 790         }
 791     };
 792 
 793     /** Look up a synthetic name in a given scope.
 794      *  @param s            The scope.
 795      *  @param name         The name.
 796      */
 797     private Symbol lookupSynthetic(Name name, Scope s) {
 798         Symbol sym = s.findFirst(name);
 799         return (sym==null || (sym.flags()&SYNTHETIC)==0) ? null : sym;
 800     }
 801 
 802     /** Look up a method in a given scope.
 803      */
 804     private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
 805         return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
 806     }
 807 
 808     private Symbol findMethodOrFailSilently(
 809             DiagnosticPosition pos,
 810             Env<AttrContext> env,
 811             Type site,
 812             Name name,
 813             List<Type> argtypes,
 814             List<Type> typeargtypes) {
 815         MethodResolutionContext resolveContext = rs.new MethodResolutionContext();
 816         resolveContext.internalResolution = true;
 817         resolveContext.silentFail = true;
 818         Symbol sym = rs.resolveQualifiedMethod(resolveContext, pos, env, site.tsym,
 819                 site, name, argtypes, typeargtypes);
 820         return sym;
 821     }
 822 
 823     /** Anon inner classes are used as access constructor tags.
 824      * accessConstructorTag will use an existing anon class if one is available,
 825      * and synthethise a class (with makeEmptyClass) if one is not available.
 826      * However, there is a small possibility that an existing class will not
 827      * be generated as expected if it is inside a conditional with a constant
 828      * expression. If that is found to be the case, create an empty class tree here.
 829      */
 830     private void checkAccessConstructorTags() {
 831         for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
 832             ClassSymbol c = l.head;
 833             if (isTranslatedClassAvailable(c))
 834                 continue;
 835             // Create class definition tree.
 836             JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
 837                     c.outermostClass(), c.flatname, false);
 838             swapAccessConstructorTag(c, cdec.sym);
 839             translated.append(cdec);
 840         }
 841     }
 842     // where


2189         ClassSymbol currentClassPrev = currentClass;
2190         MethodSymbol currentMethodSymPrev = currentMethodSym;
2191 
2192         currentClass = tree.sym;
2193         currentMethodSym = null;
2194         attrEnv = typeEnvs.remove(currentClass);
2195         if (attrEnv == null)
2196             attrEnv = prevEnv;
2197 
2198         classdefs.put(currentClass, tree);
2199 
2200         Map<Symbol, Symbol> prevProxies = proxies;
2201         proxies = new HashMap<>(proxies);
2202         List<VarSymbol> prevOuterThisStack = outerThisStack;
2203 
2204         // If this is an enum definition
2205         if ((tree.mods.flags & ENUM) != 0 &&
2206             (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2207             visitEnumDef(tree);
2208 
2209         if ((tree.mods.flags & RECORD) != 0) {
2210             visitRecordDef(tree);
2211         }
2212 
2213         // If this is a nested class, define a this$n field for
2214         // it and add to proxies.
2215         JCVariableDecl otdef = null;
2216         if (currentClass.hasOuterInstance())
2217             otdef = outerThisDef(tree.pos, currentClass);
2218 
2219         // If this is a local class, define proxies for all its free variables.
2220         List<JCVariableDecl> fvdefs = freevarDefs(
2221             tree.pos, freevars(currentClass), currentClass);
2222 
2223         // Recursively translate superclass, interfaces.
2224         tree.extending = translate(tree.extending);
2225         tree.implementing = translate(tree.implementing);
2226 
2227         if (currentClass.isLocal()) {
2228             ClassSymbol encl = currentClass.owner.enclClass();
2229             if (encl.trans_local == null) {
2230                 encl.trans_local = List.nil();
2231             }
2232             encl.trans_local = encl.trans_local.prepend(currentClass);


2262         }
2263         if (currentClass.hasOuterInstance()) {
2264             tree.defs = tree.defs.prepend(otdef);
2265             enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
2266         }
2267 
2268         proxies = prevProxies;
2269         outerThisStack = prevOuterThisStack;
2270 
2271         // Append translated tree to `translated' queue.
2272         translated.append(tree);
2273 
2274         attrEnv = prevEnv;
2275         currentClass = currentClassPrev;
2276         currentMethodSym = currentMethodSymPrev;
2277 
2278         // Return empty block {} as a placeholder for an inner class.
2279         result = make_at(tree.pos()).Block(SYNTHETIC, List.nil());
2280     }
2281 
2282     List<JCTree> accessors(JCClassDecl tree) {
2283         ListBuffer<JCTree> buffer = new ListBuffer<>();
2284         tree.defs.stream()
2285                 .filter(t -> t.hasTag(VARDEF))
2286                 .map(t -> (JCVariableDecl)t)
2287                 .filter(vd -> vd.sym.accessors.nonEmpty())
2288                 .forEach(vd -> {
2289                     for (Pair<Accessors.Kind, MethodSymbol> accessor : vd.sym.accessors) {
2290                         MethodSymbol accessorSym = accessor.snd;
2291                         if ((accessorSym.flags() & Flags.MANDATED) != 0) {
2292                             make_at(tree.pos());
2293                             switch (accessor.fst) {
2294                                 case GET:
2295                                     buffer.add(make.MethodDef(accessorSym, make.Block(0,
2296                                             List.of(make.Return(make.Ident(vd.sym))))));
2297                                     break;
2298                                 case SET:
2299                                     buffer.add(make.MethodDef(accessorSym, make.Block(0,
2300                                             List.of(make.Exec(
2301                                                     make.Assign(make.Ident(vd.sym), make.Ident(accessorSym.params.head))
2302                                                             .setType(vd.sym.type))))));
2303                                     break;
2304                                 default:
2305                                     Assert.error("Cannot get here!");
2306                             }
2307                         }
2308                     }
2309                 });
2310         return buffer.toList();
2311     }
2312 
2313     /** Translate an enum class. */
2314     private void visitEnumDef(JCClassDecl tree) {
2315         make_at(tree.pos());
2316 
2317         // add the supertype, if needed
2318         if (tree.extending == null)
2319             tree.extending = make.Type(types.supertype(tree.type));
2320 
2321         // classOfType adds a cache field to tree.defs
2322         JCExpression e_class = classOfType(tree.sym.type, tree.pos()).
2323             setType(types.erasure(syms.classType));
2324 
2325         // process each enumeration constant, adding implicit constructor parameters
2326         int nextOrdinal = 0;
2327         ListBuffer<JCExpression> values = new ListBuffer<>();
2328         ListBuffer<JCTree> enumDefs = new ListBuffer<>();
2329         ListBuffer<JCTree> otherDefs = new ListBuffer<>();
2330         for (List<JCTree> defs = tree.defs;
2331              defs.nonEmpty();
2332              defs=defs.tail) {


2446         enumDefs.appendList(otherDefs.toList());
2447         tree.defs = enumDefs.toList();
2448     }
2449         // where
2450         private MethodSymbol systemArraycopyMethod;
2451         private boolean useClone() {
2452             try {
2453                 return syms.objectType.tsym.members().findFirst(names.clone) != null;
2454             }
2455             catch (CompletionFailure e) {
2456                 return false;
2457             }
2458         }
2459 
2460     /** Translate an enumeration constant and its initializer. */
2461     private void visitEnumConstantDef(JCVariableDecl var, int ordinal) {
2462         JCNewClass varDef = (JCNewClass)var.init;
2463         varDef.args = varDef.args.
2464             prepend(makeLit(syms.intType, ordinal)).
2465             prepend(makeLit(syms.stringType, var.name.toString()));
2466     }
2467 
2468     /** Translate a record. */
2469     private void visitRecordDef(JCClassDecl tree) {
2470         make_at(tree.pos());
2471         List<VarSymbol> vars = types.recordVars(tree.type);
2472         Pool.MethodHandle[] getterMethHandles = new Pool.MethodHandle[vars.size()];
2473         int index = 0;
2474         for (VarSymbol var : vars) {
2475             if (var.owner != tree.sym) {
2476                 var = new VarSymbol(var.flags_field, var.name, var.type, tree.sym);
2477             }
2478             getterMethHandles[index] = new Pool.MethodHandle(ClassFile.REF_getField, var, types);
2479             index++;
2480         }
2481 
2482         tree.defs = tree.defs.appendList(accessors(tree));
2483         tree.defs = tree.defs.appendList(List.of(
2484                 recordEquals(tree, getterMethHandles),
2485                 recordToString(tree, vars, getterMethHandles),
2486                 recordHashCode(tree, getterMethHandles),
2487                 recordExtractor(tree, getterMethHandles),
2488                 recordReadResolve(tree)
2489         ));
2490     }
2491 
2492     JCTree recordToString(JCClassDecl tree, List<VarSymbol> vars, Pool.MethodHandle[] getterMethHandles) {
2493         make_at(tree.pos());
2494 
2495         MethodSymbol msym = lookupMethod(tree.pos(),
2496                          names.toString,
2497                          tree.sym.type,
2498                          List.nil());
2499         if ((msym.flags() & RECORD) != 0) {
2500             Name bootstrapName = names.makeToString;
2501             Object[] staticArgsValues = new Object[2 + getterMethHandles.length];
2502             staticArgsValues[0] = tree.sym;
2503             String concatNames = vars.stream()
2504                     .map(v -> v.name)
2505                     .collect(Collectors.joining(";", "", ""));
2506             staticArgsValues[1] = concatNames;
2507             int index = 2;
2508             for (Object mho : getterMethHandles) {
2509                 staticArgsValues[index] = mho;
2510                 index++;
2511             }
2512 
2513             List<Type> staticArgTypes = List.of(syms.classType,
2514                     syms.stringType,
2515                     new ArrayType(syms.methodHandleType, syms.arrayClass));
2516 
2517             JCFieldAccess qualifier = makeIndyQualifier(syms.objectMethodBuildersType,
2518                     tree, msym, staticArgTypes, staticArgsValues, bootstrapName, false);
2519 
2520             VarSymbol _this = new VarSymbol(SYNTHETIC, names._this, tree.sym.type, tree.sym);
2521 
2522             JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, List.of(make.Ident(_this)));
2523             proxyCall.type = qualifier.type;
2524             return make.MethodDef(msym, make.Block(0, List.of(make.Return(proxyCall))));
2525         } else {
2526             return make.Block(SYNTHETIC, List.nil());
2527         }
2528     }
2529 
2530     JCTree recordHashCode(JCClassDecl tree, Pool.MethodHandle[] getterMethHandles) {
2531         make_at(tree.pos());
2532         MethodSymbol msym = lookupMethod(tree.pos(),
2533                          names.hashCode,
2534                          tree.sym.type,
2535                          List.nil());
2536         if ((msym.flags() & RECORD) != 0) {
2537             Name bootstrapName = names.makeHashCode;
2538             Object[] staticArgsValues = new Object[1 + getterMethHandles.length];
2539             staticArgsValues[0] = tree.sym;
2540             int index = 1;
2541             for (Object mho : getterMethHandles) {
2542                 staticArgsValues[index] = mho;
2543                 index++;
2544             }
2545 
2546             List<Type> staticArgTypes = List.of(syms.classType,
2547                     new ArrayType(syms.methodHandleType, syms.arrayClass));
2548 
2549             JCFieldAccess qualifier = makeIndyQualifier(
2550                     syms.objectMethodBuildersType, tree, msym,
2551                     staticArgTypes, staticArgsValues, bootstrapName,
2552                     false);
2553 
2554             VarSymbol _this = new VarSymbol(SYNTHETIC, names._this, tree.sym.type, tree.sym);
2555 
2556             JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, List.of(make.Ident(_this)));
2557             proxyCall.type = qualifier.type;
2558             return make.MethodDef(msym, make.Block(0, List.of(make.Return(proxyCall))));
2559         } else {
2560             return make.Block(SYNTHETIC, List.nil());
2561         }
2562     }
2563 
2564     JCTree recordExtractor(JCClassDecl tree, Pool.MethodHandle[] getterMethHandles) {
2565         make_at(tree.pos());
2566         List<Type> fieldTypes = TreeInfo.types(TreeInfo.recordFields(tree));
2567         String argsTypeSig = '(' + argsTypeSig(fieldTypes) + ')';
2568         String extractorStr = BytecodeName.toBytecodeName("$pattern$" + tree.sym.name + "$" + argsTypeSig);
2569         Name extractorName = names.fromString(extractorStr);
2570         // public Extractor extractorName () { return ???; }
2571         MethodType extractorMT = new MethodType(List.nil(), syms.extractorType, List.nil(), syms.methodClass);
2572         MethodSymbol extractorSym = new MethodSymbol(
2573                 Flags.PUBLIC | Flags.RECORD | Flags.STATIC,
2574                 extractorName, extractorMT, tree.sym);
2575         tree.sym.members().enter(extractorSym);
2576 
2577         Name bootstrapName = names.makeLazyExtractor;
2578         Object[] staticArgsValues = new Object[1 + getterMethHandles.length];
2579         /** this method descriptor should have the same arguments as the record constructor and its
2580          *  return type should be the same as the type of the record
2581          */
2582         MethodType mt = new MethodType(fieldTypes, tree.type, List.nil(), syms.methodClass);
2583         staticArgsValues[0] = mt;
2584         int index = 1;
2585         for (Object mho : getterMethHandles) {
2586             staticArgsValues[index] = mho;
2587             index++;
2588         }
2589 
2590         List<Type> staticArgTypes = List.of(syms.methodTypeType,
2591                 new ArrayType(syms.methodHandleType, syms.arrayClass));
2592         JCFieldAccess qualifier = makeIndyQualifier(
2593                 syms.extractorType, tree, extractorSym, staticArgTypes,
2594                 staticArgsValues, bootstrapName, true);
2595 
2596         JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, List.nil());
2597         proxyCall.type = qualifier.type;
2598         return make.MethodDef(extractorSym, make.Block(0, List.of(make.Return(proxyCall))));
2599     }
2600 
2601     JCTree recordReadResolve(JCClassDecl tree) {
2602         make_at(tree.pos());
2603         Symbol msym = findMethodOrFailSilently(
2604                 tree.pos(),
2605                 attrEnv,
2606                 tree.sym.type,
2607                 names.readResolve,
2608                 List.nil(),
2609                 List.nil());
2610         if (!msym.kind.isResolutionError() && (msym.flags() & RECORD) != 0) {
2611             List<JCExpression> args = TreeInfo.recordFields(tree).map(vd -> make.Ident(vd));
2612             return make.MethodDef((MethodSymbol)msym, make.Block(0, List.of(make.Return(makeNewClass(tree.sym.type, args)))));
2613         } else {
2614             return make.Block(SYNTHETIC, List.nil());
2615         }
2616     }
2617 
2618     private String argsTypeSig(List<Type> typeList) {
2619         LowerSignatureGenerator sg = new LowerSignatureGenerator();
2620         sg.assembleSig(typeList);
2621         return sg.toString();
2622     }
2623 
2624     /**
2625      * Signature Generation
2626      */
2627     private class LowerSignatureGenerator extends Types.SignatureGenerator {
2628 
2629         /**
2630          * An output buffer for type signatures.
2631          */
2632         StringBuilder sb = new StringBuilder();
2633 
2634         LowerSignatureGenerator() {
2635             super(types);
2636         }
2637 
2638         @Override
2639         protected void append(char ch) {
2640             sb.append(ch);
2641         }
2642 
2643         @Override
2644         protected void append(byte[] ba) {
2645             sb.append(new String(ba));
2646         }
2647 
2648         @Override
2649         protected void append(Name name) {
2650             sb.append(name.toString());
2651         }
2652 
2653         @Override
2654         public String toString() {
2655             return sb.toString();
2656         }
2657     }
2658 
2659     JCTree recordEquals(JCClassDecl tree, Pool.MethodHandle[] getterMethHandles) {
2660         make_at(tree.pos());
2661         MethodSymbol msym = lookupMethod(tree.pos(),
2662                          names.equals,
2663                          tree.sym.type,
2664                          List.of(syms.objectType));
2665 
2666         if ((msym.flags() & RECORD) != 0) {
2667             Name bootstrapName = names.makeEquals;
2668             Object[] staticArgsValues = new Object[1 + getterMethHandles.length];
2669             staticArgsValues[0] = tree.sym;
2670             int index = 1;
2671             for (Object mho : getterMethHandles) {
2672                 staticArgsValues[index] = mho;
2673                 index++;
2674             }
2675 
2676             List<Type> staticArgTypes = List.of(syms.classType,
2677                     new ArrayType(syms.methodHandleType, syms.arrayClass));
2678 
2679             JCFieldAccess qualifier = makeIndyQualifier(
2680                     syms.objectMethodBuildersType, tree, msym,
2681                     staticArgTypes, staticArgsValues, bootstrapName, false);
2682 
2683             VarSymbol o = msym.params.head;
2684             o.adr = 0;
2685             VarSymbol _this = new VarSymbol(SYNTHETIC, names._this, tree.sym.type, tree.sym);
2686 
2687             JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, List.of(make.Ident(_this), make.Ident(o)));
2688             proxyCall.type = qualifier.type;
2689             return make.MethodDef(msym, make.Block(0, List.of(make.Return(proxyCall))));
2690         } else {
2691             return make.Block(SYNTHETIC, List.nil());
2692         }
2693     }
2694 
2695     JCFieldAccess makeIndyQualifier(
2696             Type site,
2697             JCClassDecl tree,
2698             MethodSymbol msym,
2699             List<Type> staticArgTypes,
2700             Object[] staticArgValues,
2701             Name bootstrapName,
2702             boolean isStatic) {
2703         List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
2704                 syms.stringType,
2705                 syms.methodTypeType).appendList(staticArgTypes);
2706 
2707         Symbol bsm = rs.resolveInternalMethod(tree.pos(), attrEnv, site,
2708                 bootstrapName, bsm_staticArgs, List.nil());
2709 
2710         MethodType indyType = msym.type.asMethodType();
2711         indyType = new MethodType(
2712                 isStatic ? List.nil() : indyType.argtypes.prepend(tree.sym.type),
2713                 indyType.restype,
2714                 indyType.thrown,
2715                 syms.methodClass
2716         );
2717         DynamicMethodSymbol dynSym = new DynamicMethodSymbol(bootstrapName,
2718                 syms.noSymbol,
2719                 ClassFile.REF_invokeStatic,
2720                 (MethodSymbol)bsm,
2721                 indyType,
2722                 staticArgValues);
2723         JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bootstrapName);
2724         qualifier.sym = dynSym;
2725         qualifier.type = msym.type.asMethodType().restype;
2726         return qualifier;
2727     }
2728 
2729     public void visitMethodDef(JCMethodDecl tree) {
2730         if (tree.name == names.init && (currentClass.flags_field&ENUM) != 0) {
2731             // Add "String $enum$name, int $enum$ordinal" to the beginning of the
2732             // argument list for each constructor of an enum.
2733             JCVariableDecl nameParam = make_at(tree.pos()).
2734                 Param(names.fromString(target.syntheticNameChar() +
2735                                        "enum" + target.syntheticNameChar() + "name"),
2736                       syms.stringType, tree.sym);
2737             nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC;
2738             JCVariableDecl ordParam = make.
2739                 Param(names.fromString(target.syntheticNameChar() +
2740                                        "enum" + target.syntheticNameChar() +
2741                                        "ordinal"),
2742                       syms.intType, tree.sym);
2743             ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC;
2744 
2745             MethodSymbol m = tree.sym;
2746             tree.params = tree.params.prepend(ordParam).prepend(nameParam);


< prev index next >