langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java
changeset 25445 603f0c93d5c9
parent 25443 9187d77f2c64
child 25602 7ed5b85cdbb2
equal deleted inserted replaced
25444:27045478cf23 25445:603f0c93d5c9
    73     private final Map<Type,Symbol> stringBufferAppend;
    73     private final Map<Type,Symbol> stringBufferAppend;
    74     private Name accessDollar;
    74     private Name accessDollar;
    75     private final Types types;
    75     private final Types types;
    76     private final Lower lower;
    76     private final Lower lower;
    77 
    77 
    78     /** Switch: GJ mode?
       
    79      */
       
    80     private final boolean allowGenerics;
       
    81 
       
    82     /** Set when Miranda method stubs are to be generated. */
       
    83     private final boolean generateIproxies;
       
    84 
       
    85     /** Format of stackmap tables to be generated. */
    78     /** Format of stackmap tables to be generated. */
    86     private final Code.StackMapFormat stackMap;
    79     private final Code.StackMapFormat stackMap;
    87 
    80 
    88     /** A type that serves as the expected type for all method expressions.
    81     /** A type that serves as the expected type for all method expressions.
    89      */
    82      */
   114         rs = Resolve.instance(context);
   107         rs = Resolve.instance(context);
   115         make = TreeMaker.instance(context);
   108         make = TreeMaker.instance(context);
   116         target = Target.instance(context);
   109         target = Target.instance(context);
   117         types = Types.instance(context);
   110         types = Types.instance(context);
   118         methodType = new MethodType(null, null, null, syms.methodClass);
   111         methodType = new MethodType(null, null, null, syms.methodClass);
   119         allowGenerics = Source.instance(context).allowGenerics();
   112         stringBufferType = syms.stringBuilderType;
   120         stringBufferType = target.useStringBuilder()
       
   121             ? syms.stringBuilderType
       
   122             : syms.stringBufferType;
       
   123         stringBufferAppend = new HashMap<>();
   113         stringBufferAppend = new HashMap<>();
   124         accessDollar = names.
   114         accessDollar = names.
   125             fromString("access" + target.syntheticNameChar());
   115             fromString("access" + target.syntheticNameChar());
   126         lower = Lower.instance(context);
   116         lower = Lower.instance(context);
   127 
   117 
   139         genCrt = options.isSet(XJCOV);
   129         genCrt = options.isSet(XJCOV);
   140         debugCode = options.isSet("debugcode");
   130         debugCode = options.isSet("debugcode");
   141         allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
   131         allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
   142         pool = new Pool(types);
   132         pool = new Pool(types);
   143 
   133 
   144         generateIproxies =
   134         // ignore cldc because we cannot have both stackmap formats
   145             target.requiresIproxy() ||
   135         this.stackMap = StackMapFormat.JSR202;
   146             options.isSet("miranda");
       
   147 
       
   148         if (target.generateStackMapTable()) {
       
   149             // ignore cldc because we cannot have both stackmap formats
       
   150             this.stackMap = StackMapFormat.JSR202;
       
   151         } else {
       
   152             if (target.generateCLDCStackmap()) {
       
   153                 this.stackMap = StackMapFormat.CLDC;
       
   154             } else {
       
   155                 this.stackMap = StackMapFormat.NONE;
       
   156             }
       
   157         }
       
   158 
   136 
   159         // by default, avoid jsr's for simple finalizers
   137         // by default, avoid jsr's for simple finalizers
   160         int setjsrlimit = 50;
   138         int setjsrlimit = 50;
   161         String jsrlimitString = options.get("jsrlimit");
   139         String jsrlimitString = options.get("jsrlimit");
   162         if (jsrlimitString != null) {
   140         if (jsrlimitString != null) {
   273         if (site.hasTag(ARRAY)) {
   251         if (site.hasTag(ARRAY)) {
   274             if (sym == syms.lengthVar ||
   252             if (sym == syms.lengthVar ||
   275                 sym.owner != syms.arrayClass)
   253                 sym.owner != syms.arrayClass)
   276                 return sym;
   254                 return sym;
   277             // array clone can be qualified by the array type in later targets
   255             // array clone can be qualified by the array type in later targets
   278             Symbol qualifier = target.arrayBinaryCompatibility()
   256             Symbol qualifier = new ClassSymbol(Flags.PUBLIC, site.tsym.name,
   279                 ? new ClassSymbol(Flags.PUBLIC, site.tsym.name,
   257                                                site, syms.noSymbol);
   280                                   site, syms.noSymbol)
       
   281                 : syms.objectType.tsym;
       
   282             return sym.clone(qualifier);
   258             return sym.clone(qualifier);
   283         }
   259         }
   284 
   260 
   285         if (sym.owner == site.tsym ||
   261         if (sym.owner == site.tsym ||
   286             (sym.flags() & (STATIC | SYNTHETIC)) == (STATIC | SYNTHETIC)) {
   262             (sym.flags() & (STATIC | SYNTHETIC)) == (STATIC | SYNTHETIC)) {
   287             return sym;
   263             return sym;
   288         }
       
   289         if (!target.obeyBinaryCompatibility())
       
   290             return rs.isAccessible(attrEnv, (TypeSymbol)sym.owner)
       
   291                 ? sym
       
   292                 : sym.clone(site.tsym);
       
   293 
       
   294         if (!target.interfaceFieldsBinaryCompatibility()) {
       
   295             if ((sym.owner.flags() & INTERFACE) != 0 && sym.kind == VAR)
       
   296                 return sym;
       
   297         }
   264         }
   298 
   265 
   299         // leave alone methods inherited from Object
   266         // leave alone methods inherited from Object
   300         // JLS 13.1.
   267         // JLS 13.1.
   301         if (sym.owner == syms.objectType.tsym)
   268         if (sym.owner == syms.objectType.tsym)
   302             return sym;
   269             return sym;
   303 
       
   304         if (!target.interfaceObjectOverridesBinaryCompatibility()) {
       
   305             if ((sym.owner.flags() & INTERFACE) != 0 &&
       
   306                 syms.objectType.tsym.members().findFirst(sym.name) != null)
       
   307                 return sym;
       
   308         }
       
   309 
   270 
   310         return sym.clone(site.tsym);
   271         return sym.clone(site.tsym);
   311     }
   272     }
   312 
   273 
   313     /** Insert a reference to given type in the constant pool,
   274     /** Insert a reference to given type in the constant pool,
   624 
   585 
   625             md.sym.appendUniqueTypeAttributes(initTAs);
   586             md.sym.appendUniqueTypeAttributes(initTAs);
   626         }
   587         }
   627     }
   588     }
   628 
   589 
   629 /* ********************************************************************
       
   630  * Adding miranda methods
       
   631  *********************************************************************/
       
   632 
       
   633     /** Add abstract methods for all methods defined in one of
       
   634      *  the interfaces of a given class,
       
   635      *  provided they are not already implemented in the class.
       
   636      *
       
   637      *  @param c      The class whose interfaces are searched for methods
       
   638      *                for which Miranda methods should be added.
       
   639      */
       
   640     void implementInterfaceMethods(ClassSymbol c) {
       
   641         implementInterfaceMethods(c, c);
       
   642     }
       
   643 
       
   644     /** Add abstract methods for all methods defined in one of
       
   645      *  the interfaces of a given class,
       
   646      *  provided they are not already implemented in the class.
       
   647      *
       
   648      *  @param c      The class whose interfaces are searched for methods
       
   649      *                for which Miranda methods should be added.
       
   650      *  @param site   The class in which a definition may be needed.
       
   651      */
       
   652     void implementInterfaceMethods(ClassSymbol c, ClassSymbol site) {
       
   653         for (List<Type> l = types.interfaces(c.type); l.nonEmpty(); l = l.tail) {
       
   654             ClassSymbol i = (ClassSymbol)l.head.tsym;
       
   655             for (Symbol sym : i.members().getSymbols(NON_RECURSIVE)) {
       
   656                 if (sym.kind == MTH && (sym.flags() & STATIC) == 0)
       
   657                 {
       
   658                     MethodSymbol absMeth = (MethodSymbol)sym;
       
   659                     MethodSymbol implMeth = absMeth.binaryImplementation(site, types);
       
   660                     if (implMeth == null)
       
   661                         addAbstractMethod(site, absMeth);
       
   662                     else if ((implMeth.flags() & IPROXY) != 0)
       
   663                         adjustAbstractMethod(site, implMeth, absMeth);
       
   664                 }
       
   665             }
       
   666             implementInterfaceMethods(i, site);
       
   667         }
       
   668     }
       
   669 
       
   670     /** Add an abstract methods to a class
       
   671      *  which implicitly implements a method defined in some interface
       
   672      *  implemented by the class. These methods are called "Miranda methods".
       
   673      *  Enter the newly created method into its enclosing class scope.
       
   674      *  Note that it is not entered into the class tree, as the emitter
       
   675      *  doesn't need to see it there to emit an abstract method.
       
   676      *
       
   677      *  @param c      The class to which the Miranda method is added.
       
   678      *  @param m      The interface method symbol for which a Miranda method
       
   679      *                is added.
       
   680      */
       
   681     private void addAbstractMethod(ClassSymbol c,
       
   682                                    MethodSymbol m) {
       
   683         MethodSymbol absMeth = new MethodSymbol(
       
   684             m.flags() | IPROXY | SYNTHETIC, m.name,
       
   685             m.type, // was c.type.memberType(m), but now only !generics supported
       
   686             c);
       
   687         c.members().enter(absMeth); // add to symbol table
       
   688     }
       
   689 
       
   690     private void adjustAbstractMethod(ClassSymbol c,
       
   691                                       MethodSymbol pm,
       
   692                                       MethodSymbol im) {
       
   693         MethodType pmt = (MethodType)pm.type;
       
   694         Type imt = types.memberType(c.type, im);
       
   695         pmt.thrown = chk.intersect(pmt.getThrownTypes(), imt.getThrownTypes());
       
   696     }
       
   697 
       
   698 /* ************************************************************************
   590 /* ************************************************************************
   699  * Traversal methods
   591  * Traversal methods
   700  *************************************************************************/
   592  *************************************************************************/
   701 
   593 
   702     /** Visitor argument: The current environment.
   594     /** Visitor argument: The current environment.
  1687                 endpc1 == endpc &&
  1579                 endpc1 == endpc &&
  1688                 handler_pc1 == handler_pc) {
  1580                 handler_pc1 == handler_pc) {
  1689                 code.addCatch(startpc1, endpc1, handler_pc1,
  1581                 code.addCatch(startpc1, endpc1, handler_pc1,
  1690                               (char)catch_type);
  1582                               (char)catch_type);
  1691             } else {
  1583             } else {
  1692                 if (!useJsrLocally && !target.generateStackMapTable()) {
  1584                 log.error(pos, "limit.code.too.large.for.try.stmt");
  1693                     useJsrLocally = true;
  1585                 nerrs++;
  1694                     throw new CodeSizeOverflow();
       
  1695                 } else {
       
  1696                     log.error(pos, "limit.code.too.large.for.try.stmt");
       
  1697                     nerrs++;
       
  1698                 }
       
  1699             }
  1586             }
  1700         }
  1587         }
  1701 
  1588 
  1702     /** Very roughly estimate the number of instructions needed for
  1589     /** Very roughly estimate the number of instructions needed for
  1703      *  the given tree.
  1590      *  the given tree.
  2359 
  2246 
  2360     public void visitSelect(JCFieldAccess tree) {
  2247     public void visitSelect(JCFieldAccess tree) {
  2361         Symbol sym = tree.sym;
  2248         Symbol sym = tree.sym;
  2362 
  2249 
  2363         if (tree.name == names._class) {
  2250         if (tree.name == names._class) {
  2364             Assert.check(target.hasClassLiterals());
       
  2365             code.emitLdc(makeRef(tree.pos(), tree.selected.type));
  2251             code.emitLdc(makeRef(tree.pos(), tree.selected.type));
  2366             result = items.makeStackItem(pt);
  2252             result = items.makeStackItem(pt);
  2367             return;
  2253             return;
  2368        }
  2254        }
  2369 
  2255 
  2470         try {
  2356         try {
  2471             attrEnv = env;
  2357             attrEnv = env;
  2472             ClassSymbol c = cdef.sym;
  2358             ClassSymbol c = cdef.sym;
  2473             this.toplevel = env.toplevel;
  2359             this.toplevel = env.toplevel;
  2474             this.endPosTable = toplevel.endPositions;
  2360             this.endPosTable = toplevel.endPositions;
  2475             // If this is a class definition requiring Miranda methods,
       
  2476             // add them.
       
  2477             if (generateIproxies &&
       
  2478                 (c.flags() & (INTERFACE|ABSTRACT)) == ABSTRACT
       
  2479                 && !allowGenerics // no Miranda methods available with generics
       
  2480                 )
       
  2481                 implementInterfaceMethods(c);
       
  2482             cdef.defs = normalizeDefs(cdef.defs, c);
  2361             cdef.defs = normalizeDefs(cdef.defs, c);
  2483             c.pool = pool;
  2362             c.pool = pool;
  2484             pool.reset();
  2363             pool.reset();
  2485             generateReferencesToPrunedTree(c, pool);
  2364             generateReferencesToPrunedTree(c, pool);
  2486             Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
  2365             Env<GenContext> localEnv = new Env<>(cdef, new GenContext());