Thu, 04 Feb 2010 10:14:28 -0800
6923080: TreeScanner.visitNewClass should scan tree.typeargs
Reviewed-by: darcy
1 /*
2 * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.javac.jvm;
28 import com.sun.tools.javac.code.*;
30 import com.sun.tools.javac.code.Symbol.*;
31 import com.sun.tools.javac.code.Type.*;
32 import com.sun.tools.javac.jvm.Code.*;
33 import com.sun.tools.javac.tree.JCTree;
35 import static com.sun.tools.javac.jvm.ByteCodes.*;
37 /** A helper class for code generation. Items are objects
38 * that stand for addressable entities in the bytecode. Each item
39 * supports a fixed protocol for loading the item on the stack, storing
40 * into it, converting it into a jump condition, and several others.
41 * There are many individual forms of items, such as local, static,
42 * indexed, or instance variables, values on the top of stack, the
43 * special values this or super, etc. Individual items are represented as
44 * inner classes in class Items.
45 *
46 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
47 * you write code that depends on this, you do so at your own risk.
48 * This code and its internal interfaces are subject to change or
49 * deletion without notice.</b>
50 */
51 public class Items {
53 /** The current constant pool.
54 */
55 Pool pool;
57 /** The current code buffer.
58 */
59 Code code;
61 /** The current symbol table.
62 */
63 Symtab syms;
65 /** Type utilities. */
66 Types types;
68 /** Items that exist only once (flyweight pattern).
69 */
70 private final Item voidItem;
71 private final Item thisItem;
72 private final Item superItem;
73 private final Item[] stackItem = new Item[TypeCodeCount];
75 public Items(Pool pool, Code code, Symtab syms, Types types) {
76 this.code = code;
77 this.pool = pool;
78 this.types = types;
79 voidItem = new Item(VOIDcode) {
80 public String toString() { return "void"; }
81 };
82 thisItem = new SelfItem(false);
83 superItem = new SelfItem(true);
84 for (int i = 0; i < VOIDcode; i++) stackItem[i] = new StackItem(i);
85 stackItem[VOIDcode] = voidItem;
86 this.syms = syms;
87 }
89 /** Make a void item
90 */
91 Item makeVoidItem() {
92 return voidItem;
93 }
94 /** Make an item representing `this'.
95 */
96 Item makeThisItem() {
97 return thisItem;
98 }
100 /** Make an item representing `super'.
101 */
102 Item makeSuperItem() {
103 return superItem;
104 }
106 /** Make an item representing a value on stack.
107 * @param type The value's type.
108 */
109 Item makeStackItem(Type type) {
110 return stackItem[Code.typecode(type)];
111 }
113 /** Make an item representing an indexed expression.
114 * @param type The expression's type.
115 */
116 Item makeIndexedItem(Type type) {
117 return new IndexedItem(type);
118 }
120 /** Make an item representing a local variable.
121 * @param v The represented variable.
122 */
123 LocalItem makeLocalItem(VarSymbol v) {
124 return new LocalItem(v.erasure(types), v.adr);
125 }
127 /** Make an item representing a local anonymous variable.
128 * @param type The represented variable's type.
129 * @param reg The represented variable's register.
130 */
131 private LocalItem makeLocalItem(Type type, int reg) {
132 return new LocalItem(type, reg);
133 }
135 /** Make an item representing a static variable or method.
136 * @param member The represented symbol.
137 */
138 Item makeStaticItem(Symbol member) {
139 return new StaticItem(member);
140 }
142 /** Make an item representing a dynamically invoked method.
143 * @param member The represented symbol.
144 */
145 Item makeDynamicItem(Symbol member) {
146 return new DynamicItem(member);
147 }
149 /** Make an item representing an instance variable or method.
150 * @param member The represented symbol.
151 * @param nonvirtual Is the reference not virtual? (true for constructors
152 * and private members).
153 */
154 Item makeMemberItem(Symbol member, boolean nonvirtual) {
155 return new MemberItem(member, nonvirtual);
156 }
158 /** Make an item representing a literal.
159 * @param type The literal's type.
160 * @param value The literal's value.
161 */
162 Item makeImmediateItem(Type type, Object value) {
163 return new ImmediateItem(type, value);
164 }
166 /** Make an item representing an assignment expression.
167 * @param lhs The item representing the assignment's left hand side.
168 */
169 Item makeAssignItem(Item lhs) {
170 return new AssignItem(lhs);
171 }
173 /** Make an item representing a conditional or unconditional jump.
174 * @param opcode The jump's opcode.
175 * @param trueJumps A chain encomassing all jumps that can be taken
176 * if the condition evaluates to true.
177 * @param falseJumps A chain encomassing all jumps that can be taken
178 * if the condition evaluates to false.
179 */
180 CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) {
181 return new CondItem(opcode, trueJumps, falseJumps);
182 }
184 /** Make an item representing a conditional or unconditional jump.
185 * @param opcode The jump's opcode.
186 */
187 CondItem makeCondItem(int opcode) {
188 return makeCondItem(opcode, null, null);
189 }
191 /** The base class of all items, which implements default behavior.
192 */
193 abstract class Item {
195 /** The type code of values represented by this item.
196 */
197 int typecode;
199 Item(int typecode) {
200 this.typecode = typecode;
201 }
203 /** Generate code to load this item onto stack.
204 */
205 Item load() {
206 throw new AssertionError();
207 }
209 /** Generate code to store top of stack into this item.
210 */
211 void store() {
212 throw new AssertionError("store unsupported: " + this);
213 }
215 /** Generate code to invoke method represented by this item.
216 */
217 Item invoke() {
218 throw new AssertionError(this);
219 }
221 /** Generate code to use this item twice.
222 */
223 void duplicate() {}
225 /** Generate code to avoid having to use this item.
226 */
227 void drop() {}
229 /** Generate code to stash a copy of top of stack - of typecode toscode -
230 * under this item.
231 */
232 void stash(int toscode) {
233 stackItem[toscode].duplicate();
234 }
236 /** Generate code to turn item into a testable condition.
237 */
238 CondItem mkCond() {
239 load();
240 return makeCondItem(ifne);
241 }
243 /** Generate code to coerce item to given type code.
244 * @param targetcode The type code to coerce to.
245 */
246 Item coerce(int targetcode) {
247 if (typecode == targetcode)
248 return this;
249 else {
250 load();
251 int typecode1 = Code.truncate(typecode);
252 int targetcode1 = Code.truncate(targetcode);
253 if (typecode1 != targetcode1) {
254 int offset = targetcode1 > typecode1 ? targetcode1 - 1
255 : targetcode1;
256 code.emitop0(i2l + typecode1 * 3 + offset);
257 }
258 if (targetcode != targetcode1) {
259 code.emitop0(int2byte + targetcode - BYTEcode);
260 }
261 return stackItem[targetcode];
262 }
263 }
265 /** Generate code to coerce item to given type.
266 * @param targettype The type to coerce to.
267 */
268 Item coerce(Type targettype) {
269 return coerce(Code.typecode(targettype));
270 }
272 /** Return the width of this item on stack as a number of words.
273 */
274 int width() {
275 return 0;
276 }
278 public abstract String toString();
279 }
281 /** An item representing a value on stack.
282 */
283 class StackItem extends Item {
285 StackItem(int typecode) {
286 super(typecode);
287 }
289 Item load() {
290 return this;
291 }
293 void duplicate() {
294 code.emitop0(width() == 2 ? dup2 : dup);
295 }
297 void drop() {
298 code.emitop0(width() == 2 ? pop2 : pop);
299 }
301 void stash(int toscode) {
302 code.emitop0(
303 (width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1));
304 }
306 int width() {
307 return Code.width(typecode);
308 }
310 public String toString() {
311 return "stack(" + typecodeNames[typecode] + ")";
312 }
313 }
315 /** An item representing an indexed expression.
316 */
317 class IndexedItem extends Item {
319 IndexedItem(Type type) {
320 super(Code.typecode(type));
321 }
323 Item load() {
324 code.emitop0(iaload + typecode);
325 return stackItem[typecode];
326 }
328 void store() {
329 code.emitop0(iastore + typecode);
330 }
332 void duplicate() {
333 code.emitop0(dup2);
334 }
336 void drop() {
337 code.emitop0(pop2);
338 }
340 void stash(int toscode) {
341 code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1));
342 }
344 int width() {
345 return 2;
346 }
348 public String toString() {
349 return "indexed(" + ByteCodes.typecodeNames[typecode] + ")";
350 }
351 }
353 /** An item representing `this' or `super'.
354 */
355 class SelfItem extends Item {
357 /** Flag which determines whether this item represents `this' or `super'.
358 */
359 boolean isSuper;
361 SelfItem(boolean isSuper) {
362 super(OBJECTcode);
363 this.isSuper = isSuper;
364 }
366 Item load() {
367 code.emitop0(aload_0);
368 return stackItem[typecode];
369 }
371 public String toString() {
372 return isSuper ? "super" : "this";
373 }
374 }
376 /** An item representing a local variable.
377 */
378 class LocalItem extends Item {
380 /** The variable's register.
381 */
382 int reg;
384 /** The variable's type.
385 */
386 Type type;
388 LocalItem(Type type, int reg) {
389 super(Code.typecode(type));
390 assert reg >= 0;
391 this.type = type;
392 this.reg = reg;
393 }
395 Item load() {
396 if (reg <= 3)
397 code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg);
398 else
399 code.emitop1w(iload + Code.truncate(typecode), reg);
400 return stackItem[typecode];
401 }
403 void store() {
404 if (reg <= 3)
405 code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg);
406 else
407 code.emitop1w(istore + Code.truncate(typecode), reg);
408 code.setDefined(reg);
409 }
411 void incr(int x) {
412 if (typecode == INTcode && x >= -32768 && x <= 32767) {
413 code.emitop1w(iinc, reg, x);
414 } else {
415 load();
416 if (x >= 0) {
417 makeImmediateItem(syms.intType, x).load();
418 code.emitop0(iadd);
419 } else {
420 makeImmediateItem(syms.intType, -x).load();
421 code.emitop0(isub);
422 }
423 makeStackItem(syms.intType).coerce(typecode);
424 store();
425 }
426 }
428 public String toString() {
429 return "localItem(type=" + type + "; reg=" + reg + ")";
430 }
431 }
433 /** An item representing a static variable or method.
434 */
435 class StaticItem extends Item {
437 /** The represented symbol.
438 */
439 Symbol member;
441 StaticItem(Symbol member) {
442 super(Code.typecode(member.erasure(types)));
443 this.member = member;
444 }
446 Item load() {
447 code.emitop2(getstatic, pool.put(member));
448 return stackItem[typecode];
449 }
451 void store() {
452 code.emitop2(putstatic, pool.put(member));
453 }
455 Item invoke() {
456 MethodType mtype = (MethodType)member.erasure(types);
457 int rescode = Code.typecode(mtype.restype);
458 code.emitInvokestatic(pool.put(member), mtype);
459 return stackItem[rescode];
460 }
462 public String toString() {
463 return "static(" + member + ")";
464 }
465 }
467 /** An item representing a dynamic call site.
468 */
469 class DynamicItem extends StaticItem {
470 DynamicItem(Symbol member) {
471 super(member);
472 assert member.owner == syms.invokeDynamicType.tsym;
473 }
475 Item load() {
476 assert false;
477 return null;
478 }
480 void store() {
481 assert false;
482 }
484 Item invoke() {
485 // assert target.hasNativeInvokeDynamic();
486 MethodType mtype = (MethodType)member.erasure(types);
487 int rescode = Code.typecode(mtype.restype);
488 ClassFile.NameAndType descr = new ClassFile.NameAndType(member.name, mtype);
489 code.emitInvokedynamic(pool.put(descr), mtype);
490 return stackItem[rescode];
491 }
493 public String toString() {
494 return "dynamic(" + member + ")";
495 }
496 }
499 /** An item representing an instance variable or method.
500 */
501 class MemberItem extends Item {
503 /** The represented symbol.
504 */
505 Symbol member;
507 /** Flag that determines whether or not access is virtual.
508 */
509 boolean nonvirtual;
511 MemberItem(Symbol member, boolean nonvirtual) {
512 super(Code.typecode(member.erasure(types)));
513 this.member = member;
514 this.nonvirtual = nonvirtual;
515 }
517 Item load() {
518 code.emitop2(getfield, pool.put(member));
519 return stackItem[typecode];
520 }
522 void store() {
523 code.emitop2(putfield, pool.put(member));
524 }
526 Item invoke() {
527 MethodType mtype = (MethodType)member.externalType(types);
528 int rescode = Code.typecode(mtype.restype);
529 if ((member.owner.flags() & Flags.INTERFACE) != 0) {
530 code.emitInvokeinterface(pool.put(member), mtype);
531 } else if (nonvirtual) {
532 code.emitInvokespecial(pool.put(member), mtype);
533 } else {
534 code.emitInvokevirtual(pool.put(member), mtype);
535 }
536 return stackItem[rescode];
537 }
539 void duplicate() {
540 stackItem[OBJECTcode].duplicate();
541 }
543 void drop() {
544 stackItem[OBJECTcode].drop();
545 }
547 void stash(int toscode) {
548 stackItem[OBJECTcode].stash(toscode);
549 }
551 int width() {
552 return 1;
553 }
555 public String toString() {
556 return "member(" + member + (nonvirtual ? " nonvirtual)" : ")");
557 }
558 }
560 /** An item representing a literal.
561 */
562 class ImmediateItem extends Item {
564 /** The literal's value.
565 */
566 Object value;
568 ImmediateItem(Type type, Object value) {
569 super(Code.typecode(type));
570 this.value = value;
571 }
573 private void ldc() {
574 int idx = pool.put(value);
575 if (typecode == LONGcode || typecode == DOUBLEcode) {
576 code.emitop2(ldc2w, idx);
577 } else if (idx <= 255) {
578 code.emitop1(ldc1, idx);
579 } else {
580 code.emitop2(ldc2, idx);
581 }
582 }
584 Item load() {
585 switch (typecode) {
586 case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
587 int ival = ((Number)value).intValue();
588 if (-1 <= ival && ival <= 5)
589 code.emitop0(iconst_0 + ival);
590 else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
591 code.emitop1(bipush, ival);
592 else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
593 code.emitop2(sipush, ival);
594 else
595 ldc();
596 break;
597 case LONGcode:
598 long lval = ((Number)value).longValue();
599 if (lval == 0 || lval == 1)
600 code.emitop0(lconst_0 + (int)lval);
601 else
602 ldc();
603 break;
604 case FLOATcode:
605 float fval = ((Number)value).floatValue();
606 if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
607 code.emitop0(fconst_0 + (int)fval);
608 else {
609 ldc();
610 }
611 break;
612 case DOUBLEcode:
613 double dval = ((Number)value).doubleValue();
614 if (isPosZero(dval) || dval == 1.0)
615 code.emitop0(dconst_0 + (int)dval);
616 else
617 ldc();
618 break;
619 case OBJECTcode:
620 ldc();
621 break;
622 default:
623 assert false;
624 }
625 return stackItem[typecode];
626 }
627 //where
628 /** Return true iff float number is positive 0.
629 */
630 private boolean isPosZero(float x) {
631 return x == 0.0f && 1.0f / x > 0.0f;
632 }
633 /** Return true iff double number is positive 0.
634 */
635 private boolean isPosZero(double x) {
636 return x == 0.0d && 1.0d / x > 0.0d;
637 }
639 CondItem mkCond() {
640 int ival = ((Number)value).intValue();
641 return makeCondItem(ival != 0 ? goto_ : dontgoto);
642 }
644 Item coerce(int targetcode) {
645 if (typecode == targetcode) {
646 return this;
647 } else {
648 switch (targetcode) {
649 case INTcode:
650 if (Code.truncate(typecode) == INTcode)
651 return this;
652 else
653 return new ImmediateItem(
654 syms.intType,
655 ((Number)value).intValue());
656 case LONGcode:
657 return new ImmediateItem(
658 syms.longType,
659 ((Number)value).longValue());
660 case FLOATcode:
661 return new ImmediateItem(
662 syms.floatType,
663 ((Number)value).floatValue());
664 case DOUBLEcode:
665 return new ImmediateItem(
666 syms.doubleType,
667 ((Number)value).doubleValue());
668 case BYTEcode:
669 return new ImmediateItem(
670 syms.byteType,
671 (int)(byte)((Number)value).intValue());
672 case CHARcode:
673 return new ImmediateItem(
674 syms.charType,
675 (int)(char)((Number)value).intValue());
676 case SHORTcode:
677 return new ImmediateItem(
678 syms.shortType,
679 (int)(short)((Number)value).intValue());
680 default:
681 return super.coerce(targetcode);
682 }
683 }
684 }
686 public String toString() {
687 return "immediate(" + value + ")";
688 }
689 }
691 /** An item representing an assignment expressions.
692 */
693 class AssignItem extends Item {
695 /** The item representing the assignment's left hand side.
696 */
697 Item lhs;
699 AssignItem(Item lhs) {
700 super(lhs.typecode);
701 this.lhs = lhs;
702 }
704 Item load() {
705 lhs.stash(typecode);
706 lhs.store();
707 return stackItem[typecode];
708 }
710 void duplicate() {
711 load().duplicate();
712 }
714 void drop() {
715 lhs.store();
716 }
718 void stash(int toscode) {
719 assert false;
720 }
722 int width() {
723 return lhs.width() + Code.width(typecode);
724 }
726 public String toString() {
727 return "assign(lhs = " + lhs + ")";
728 }
729 }
731 /** An item representing a conditional or unconditional jump.
732 */
733 class CondItem extends Item {
735 /** A chain encomassing all jumps that can be taken
736 * if the condition evaluates to true.
737 */
738 Chain trueJumps;
740 /** A chain encomassing all jumps that can be taken
741 * if the condition evaluates to false.
742 */
743 Chain falseJumps;
745 /** The jump's opcode.
746 */
747 int opcode;
749 /*
750 * An abstract syntax tree of this item. It is needed
751 * for branch entries in 'CharacterRangeTable' attribute.
752 */
753 JCTree tree;
755 CondItem(int opcode, Chain truejumps, Chain falsejumps) {
756 super(BYTEcode);
757 this.opcode = opcode;
758 this.trueJumps = truejumps;
759 this.falseJumps = falsejumps;
760 }
762 Item load() {
763 Chain trueChain = null;
764 Chain falseChain = jumpFalse();
765 if (!isFalse()) {
766 code.resolve(trueJumps);
767 code.emitop0(iconst_1);
768 trueChain = code.branch(goto_);
769 }
770 if (falseChain != null) {
771 code.resolve(falseChain);
772 code.emitop0(iconst_0);
773 }
774 code.resolve(trueChain);
775 return stackItem[typecode];
776 }
778 void duplicate() {
779 load().duplicate();
780 }
782 void drop() {
783 load().drop();
784 }
786 void stash(int toscode) {
787 assert false;
788 }
790 CondItem mkCond() {
791 return this;
792 }
794 Chain jumpTrue() {
795 if (tree == null) return code.mergeChains(trueJumps, code.branch(opcode));
796 // we should proceed further in -Xjcov mode only
797 int startpc = code.curPc();
798 Chain c = code.mergeChains(trueJumps, code.branch(opcode));
799 code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curPc());
800 return c;
801 }
803 Chain jumpFalse() {
804 if (tree == null) return code.mergeChains(falseJumps, code.branch(code.negate(opcode)));
805 // we should proceed further in -Xjcov mode only
806 int startpc = code.curPc();
807 Chain c = code.mergeChains(falseJumps, code.branch(code.negate(opcode)));
808 code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curPc());
809 return c;
810 }
812 CondItem negate() {
813 CondItem c = new CondItem(code.negate(opcode), falseJumps, trueJumps);
814 c.tree = tree;
815 return c;
816 }
818 int width() {
819 // a CondItem doesn't have a size on the stack per se.
820 throw new AssertionError();
821 }
823 boolean isTrue() {
824 return falseJumps == null && opcode == goto_;
825 }
827 boolean isFalse() {
828 return trueJumps == null && opcode == dontgoto;
829 }
831 public String toString() {
832 return "cond(" + Code.mnem(opcode) + ")";
833 }
834 }
835 }