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. |
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()); |