Tue, 25 Jun 2013 16:12:53 +0100
8017104: javac should have a class for primitive types that inherits from Type
Reviewed-by: jjg
1 /*
2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
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 */
26 package com.sun.tools.javac.jvm;
28 import com.sun.tools.javac.code.*;
29 import com.sun.tools.javac.code.Symbol.*;
30 import com.sun.tools.javac.code.Types.UniqueType;
31 import com.sun.tools.javac.util.*;
32 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
34 import static com.sun.tools.javac.code.TypeTag.BOT;
35 import static com.sun.tools.javac.code.TypeTag.INT;
36 import static com.sun.tools.javac.jvm.ByteCodes.*;
37 import static com.sun.tools.javac.jvm.UninitializedType.*;
38 import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
40 /** An internal structure that corresponds to the code attribute of
41 * methods in a classfile. The class also provides some utility operations to
42 * generate bytecode instructions.
43 *
44 * <p><b>This is NOT part of any supported API.
45 * If you write code that depends on this, you do so at your own risk.
46 * This code and its internal interfaces are subject to change or
47 * deletion without notice.</b>
48 */
49 public class Code {
51 public final boolean debugCode;
52 public final boolean needStackMap;
54 public enum StackMapFormat {
55 NONE,
56 CLDC {
57 Name getAttributeName(Names names) {
58 return names.StackMap;
59 }
60 },
61 JSR202 {
62 Name getAttributeName(Names names) {
63 return names.StackMapTable;
64 }
65 };
66 Name getAttributeName(Names names) {
67 return names.empty;
68 }
69 }
71 final Types types;
72 final Symtab syms;
74 /*---------- classfile fields: --------------- */
76 /** The maximum stack size.
77 */
78 public int max_stack = 0;
80 /** The maximum number of local variable slots.
81 */
82 public int max_locals = 0;
84 /** The code buffer.
85 */
86 public byte[] code = new byte[64];
88 /** the current code pointer.
89 */
90 public int cp = 0;
92 /** Check the code against VM spec limits; if
93 * problems report them and return true.
94 */
95 public boolean checkLimits(DiagnosticPosition pos, Log log) {
96 if (cp > ClassFile.MAX_CODE) {
97 log.error(pos, "limit.code");
98 return true;
99 }
100 if (max_locals > ClassFile.MAX_LOCALS) {
101 log.error(pos, "limit.locals");
102 return true;
103 }
104 if (max_stack > ClassFile.MAX_STACK) {
105 log.error(pos, "limit.stack");
106 return true;
107 }
108 return false;
109 }
111 /** A buffer for expression catch data. Each enter is a vector
112 * of four unsigned shorts.
113 */
114 ListBuffer<char[]> catchInfo = new ListBuffer<char[]>();
116 /** A buffer for line number information. Each entry is a vector
117 * of two unsigned shorts.
118 */
119 List<char[]> lineInfo = List.nil(); // handled in stack fashion
121 /** The CharacterRangeTable
122 */
123 public CRTable crt;
125 /*---------- internal fields: --------------- */
127 /** Are we generating code with jumps ≥ 32K?
128 */
129 public boolean fatcode;
131 /** Code generation enabled?
132 */
133 private boolean alive = true;
135 /** The current machine state (registers and stack).
136 */
137 State state;
139 /** Is it forbidden to compactify code, because something is
140 * pointing to current location?
141 */
142 private boolean fixedPc = false;
144 /** The next available register.
145 */
146 public int nextreg = 0;
148 /** A chain for jumps to be resolved before the next opcode is emitted.
149 * We do this lazily to avoid jumps to jumps.
150 */
151 Chain pendingJumps = null;
153 /** The position of the currently statement, if we are at the
154 * start of this statement, NOPOS otherwise.
155 * We need this to emit line numbers lazily, which we need to do
156 * because of jump-to-jump optimization.
157 */
158 int pendingStatPos = Position.NOPOS;
160 /** Set true when a stackMap is needed at the current PC. */
161 boolean pendingStackMap = false;
163 /** The stack map format to be generated. */
164 StackMapFormat stackMap;
166 /** Switch: emit variable debug info.
167 */
168 boolean varDebugInfo;
170 /** Switch: emit line number info.
171 */
172 boolean lineDebugInfo;
174 /** Emit line number info if map supplied
175 */
176 Position.LineMap lineMap;
178 /** The constant pool of the current class.
179 */
180 final Pool pool;
182 final MethodSymbol meth;
184 /** Construct a code object, given the settings of the fatcode,
185 * debugging info switches and the CharacterRangeTable.
186 */
187 public Code(MethodSymbol meth,
188 boolean fatcode,
189 Position.LineMap lineMap,
190 boolean varDebugInfo,
191 StackMapFormat stackMap,
192 boolean debugCode,
193 CRTable crt,
194 Symtab syms,
195 Types types,
196 Pool pool) {
197 this.meth = meth;
198 this.fatcode = fatcode;
199 this.lineMap = lineMap;
200 this.lineDebugInfo = lineMap != null;
201 this.varDebugInfo = varDebugInfo;
202 this.crt = crt;
203 this.syms = syms;
204 this.types = types;
205 this.debugCode = debugCode;
206 this.stackMap = stackMap;
207 switch (stackMap) {
208 case CLDC:
209 case JSR202:
210 this.needStackMap = true;
211 break;
212 default:
213 this.needStackMap = false;
214 }
215 state = new State();
216 lvar = new LocalVar[20];
217 this.pool = pool;
218 }
221 /* **************************************************************************
222 * Typecodes & related stuff
223 ****************************************************************************/
225 /** Given a type, return its type code (used implicitly in the
226 * JVM architecture).
227 */
228 public static int typecode(Type type) {
229 switch (type.getTag()) {
230 case BYTE: return BYTEcode;
231 case SHORT: return SHORTcode;
232 case CHAR: return CHARcode;
233 case INT: return INTcode;
234 case LONG: return LONGcode;
235 case FLOAT: return FLOATcode;
236 case DOUBLE: return DOUBLEcode;
237 case BOOLEAN: return BYTEcode;
238 case VOID: return VOIDcode;
239 case CLASS:
240 case ARRAY:
241 case METHOD:
242 case BOT:
243 case TYPEVAR:
244 case UNINITIALIZED_THIS:
245 case UNINITIALIZED_OBJECT:
246 return OBJECTcode;
247 default: throw new AssertionError("typecode " + type.getTag());
248 }
249 }
251 /** Collapse type code for subtypes of int to INTcode.
252 */
253 public static int truncate(int tc) {
254 switch (tc) {
255 case BYTEcode: case SHORTcode: case CHARcode: return INTcode;
256 default: return tc;
257 }
258 }
260 /** The width in bytes of objects of the type.
261 */
262 public static int width(int typecode) {
263 switch (typecode) {
264 case LONGcode: case DOUBLEcode: return 2;
265 case VOIDcode: return 0;
266 default: return 1;
267 }
268 }
270 public static int width(Type type) {
271 return type == null ? 1 : width(typecode(type));
272 }
274 /** The total width taken up by a vector of objects.
275 */
276 public static int width(List<Type> types) {
277 int w = 0;
278 for (List<Type> l = types; l.nonEmpty(); l = l.tail)
279 w = w + width(l.head);
280 return w;
281 }
283 /** Given a type, return its code for allocating arrays of that type.
284 */
285 public static int arraycode(Type type) {
286 switch (type.getTag()) {
287 case BYTE: return 8;
288 case BOOLEAN: return 4;
289 case SHORT: return 9;
290 case CHAR: return 5;
291 case INT: return 10;
292 case LONG: return 11;
293 case FLOAT: return 6;
294 case DOUBLE: return 7;
295 case CLASS: return 0;
296 case ARRAY: return 1;
297 default: throw new AssertionError("arraycode " + type);
298 }
299 }
302 /* **************************************************************************
303 * Emit code
304 ****************************************************************************/
306 /** The current output code pointer.
307 */
308 public int curPc() {
309 if (pendingJumps != null) resolvePending();
310 if (pendingStatPos != Position.NOPOS) markStatBegin();
311 fixedPc = true;
312 return cp;
313 }
315 /** Emit a byte of code.
316 */
317 private void emit1(int od) {
318 if (!alive) return;
319 code = ArrayUtils.ensureCapacity(code, cp);
320 code[cp++] = (byte)od;
321 }
323 /** Emit two bytes of code.
324 */
325 private void emit2(int od) {
326 if (!alive) return;
327 if (cp + 2 > code.length) {
328 emit1(od >> 8);
329 emit1(od);
330 } else {
331 code[cp++] = (byte)(od >> 8);
332 code[cp++] = (byte)od;
333 }
334 }
336 /** Emit four bytes of code.
337 */
338 public void emit4(int od) {
339 if (!alive) return;
340 if (cp + 4 > code.length) {
341 emit1(od >> 24);
342 emit1(od >> 16);
343 emit1(od >> 8);
344 emit1(od);
345 } else {
346 code[cp++] = (byte)(od >> 24);
347 code[cp++] = (byte)(od >> 16);
348 code[cp++] = (byte)(od >> 8);
349 code[cp++] = (byte)od;
350 }
351 }
353 /** Emit an opcode.
354 */
355 private void emitop(int op) {
356 if (pendingJumps != null) resolvePending();
357 if (alive) {
358 if (pendingStatPos != Position.NOPOS)
359 markStatBegin();
360 if (pendingStackMap) {
361 pendingStackMap = false;
362 emitStackMap();
363 }
364 if (debugCode)
365 System.err.println("emit@" + cp + " stack=" +
366 state.stacksize + ": " +
367 mnem(op));
368 emit1(op);
369 }
370 }
372 void postop() {
373 Assert.check(alive || state.stacksize == 0);
374 }
376 /** Emit a ldc (or ldc_w) instruction, taking into account operand size
377 */
378 public void emitLdc(int od) {
379 if (od <= 255) {
380 emitop1(ldc1, od);
381 }
382 else {
383 emitop2(ldc2, od);
384 }
385 }
387 /** Emit a multinewarray instruction.
388 */
389 public void emitMultianewarray(int ndims, int type, Type arrayType) {
390 emitop(multianewarray);
391 if (!alive) return;
392 emit2(type);
393 emit1(ndims);
394 state.pop(ndims);
395 state.push(arrayType);
396 }
398 /** Emit newarray.
399 */
400 public void emitNewarray(int elemcode, Type arrayType) {
401 emitop(newarray);
402 if (!alive) return;
403 emit1(elemcode);
404 state.pop(1); // count
405 state.push(arrayType);
406 }
408 /** Emit anewarray.
409 */
410 public void emitAnewarray(int od, Type arrayType) {
411 emitop(anewarray);
412 if (!alive) return;
413 emit2(od);
414 state.pop(1);
415 state.push(arrayType);
416 }
418 /** Emit an invokeinterface instruction.
419 */
420 public void emitInvokeinterface(int meth, Type mtype) {
421 int argsize = width(mtype.getParameterTypes());
422 emitop(invokeinterface);
423 if (!alive) return;
424 emit2(meth);
425 emit1(argsize + 1);
426 emit1(0);
427 state.pop(argsize + 1);
428 state.push(mtype.getReturnType());
429 }
431 /** Emit an invokespecial instruction.
432 */
433 public void emitInvokespecial(int meth, Type mtype) {
434 int argsize = width(mtype.getParameterTypes());
435 emitop(invokespecial);
436 if (!alive) return;
437 emit2(meth);
438 Symbol sym = (Symbol)pool.pool[meth];
439 state.pop(argsize);
440 if (sym.isConstructor())
441 state.markInitialized((UninitializedType)state.peek());
442 state.pop(1);
443 state.push(mtype.getReturnType());
444 }
446 /** Emit an invokestatic instruction.
447 */
448 public void emitInvokestatic(int meth, Type mtype) {
449 int argsize = width(mtype.getParameterTypes());
450 emitop(invokestatic);
451 if (!alive) return;
452 emit2(meth);
453 state.pop(argsize);
454 state.push(mtype.getReturnType());
455 }
457 /** Emit an invokevirtual instruction.
458 */
459 public void emitInvokevirtual(int meth, Type mtype) {
460 int argsize = width(mtype.getParameterTypes());
461 emitop(invokevirtual);
462 if (!alive) return;
463 emit2(meth);
464 state.pop(argsize + 1);
465 state.push(mtype.getReturnType());
466 }
468 /** Emit an invokedynamic instruction.
469 */
470 public void emitInvokedynamic(int desc, Type mtype) {
471 // N.B. this format is under consideration by the JSR 292 EG
472 int argsize = width(mtype.getParameterTypes());
473 int prevPos = pendingStatPos;
474 try {
475 //disable line number generation (we could have used 'emit1', that
476 //bypasses stackmap generation - which is needed for indy calls)
477 pendingStatPos = Position.NOPOS;
478 emitop(invokedynamic);
479 } finally {
480 pendingStatPos = prevPos;
481 }
482 if (!alive) return;
483 emit2(desc);
484 emit2(0);
485 state.pop(argsize);
486 state.push(mtype.getReturnType());
487 }
489 /** Emit an opcode with no operand field.
490 */
491 public void emitop0(int op) {
492 emitop(op);
493 if (!alive) return;
494 switch (op) {
495 case aaload: {
496 state.pop(1);// index
497 Type a = state.stack[state.stacksize-1];
498 state.pop(1);
499 //sometimes 'null type' is treated as a one-dimensional array type
500 //see Gen.visitLiteral - we should handle this case accordingly
501 Type stackType = a.hasTag(BOT) ?
502 syms.objectType :
503 types.erasure(types.elemtype(a));
504 state.push(stackType); }
505 break;
506 case goto_:
507 markDead();
508 break;
509 case nop:
510 case ineg:
511 case lneg:
512 case fneg:
513 case dneg:
514 break;
515 case aconst_null:
516 state.push(syms.botType);
517 break;
518 case iconst_m1:
519 case iconst_0:
520 case iconst_1:
521 case iconst_2:
522 case iconst_3:
523 case iconst_4:
524 case iconst_5:
525 case iload_0:
526 case iload_1:
527 case iload_2:
528 case iload_3:
529 state.push(syms.intType);
530 break;
531 case lconst_0:
532 case lconst_1:
533 case lload_0:
534 case lload_1:
535 case lload_2:
536 case lload_3:
537 state.push(syms.longType);
538 break;
539 case fconst_0:
540 case fconst_1:
541 case fconst_2:
542 case fload_0:
543 case fload_1:
544 case fload_2:
545 case fload_3:
546 state.push(syms.floatType);
547 break;
548 case dconst_0:
549 case dconst_1:
550 case dload_0:
551 case dload_1:
552 case dload_2:
553 case dload_3:
554 state.push(syms.doubleType);
555 break;
556 case aload_0:
557 state.push(lvar[0].sym.type);
558 break;
559 case aload_1:
560 state.push(lvar[1].sym.type);
561 break;
562 case aload_2:
563 state.push(lvar[2].sym.type);
564 break;
565 case aload_3:
566 state.push(lvar[3].sym.type);
567 break;
568 case iaload:
569 case baload:
570 case caload:
571 case saload:
572 state.pop(2);
573 state.push(syms.intType);
574 break;
575 case laload:
576 state.pop(2);
577 state.push(syms.longType);
578 break;
579 case faload:
580 state.pop(2);
581 state.push(syms.floatType);
582 break;
583 case daload:
584 state.pop(2);
585 state.push(syms.doubleType);
586 break;
587 case istore_0:
588 case istore_1:
589 case istore_2:
590 case istore_3:
591 case fstore_0:
592 case fstore_1:
593 case fstore_2:
594 case fstore_3:
595 case astore_0:
596 case astore_1:
597 case astore_2:
598 case astore_3:
599 case pop:
600 case lshr:
601 case lshl:
602 case lushr:
603 state.pop(1);
604 break;
605 case areturn:
606 case ireturn:
607 case freturn:
608 Assert.check(state.nlocks == 0);
609 state.pop(1);
610 markDead();
611 break;
612 case athrow:
613 state.pop(1);
614 markDead();
615 break;
616 case lstore_0:
617 case lstore_1:
618 case lstore_2:
619 case lstore_3:
620 case dstore_0:
621 case dstore_1:
622 case dstore_2:
623 case dstore_3:
624 case pop2:
625 state.pop(2);
626 break;
627 case lreturn:
628 case dreturn:
629 Assert.check(state.nlocks == 0);
630 state.pop(2);
631 markDead();
632 break;
633 case dup:
634 state.push(state.stack[state.stacksize-1]);
635 break;
636 case return_:
637 Assert.check(state.nlocks == 0);
638 markDead();
639 break;
640 case arraylength:
641 state.pop(1);
642 state.push(syms.intType);
643 break;
644 case isub:
645 case iadd:
646 case imul:
647 case idiv:
648 case imod:
649 case ishl:
650 case ishr:
651 case iushr:
652 case iand:
653 case ior:
654 case ixor:
655 state.pop(1);
656 // state.pop(1);
657 // state.push(syms.intType);
658 break;
659 case aastore:
660 state.pop(3);
661 break;
662 case land:
663 case lor:
664 case lxor:
665 case lmod:
666 case ldiv:
667 case lmul:
668 case lsub:
669 case ladd:
670 state.pop(2);
671 break;
672 case lcmp:
673 state.pop(4);
674 state.push(syms.intType);
675 break;
676 case l2i:
677 state.pop(2);
678 state.push(syms.intType);
679 break;
680 case i2l:
681 state.pop(1);
682 state.push(syms.longType);
683 break;
684 case i2f:
685 state.pop(1);
686 state.push(syms.floatType);
687 break;
688 case i2d:
689 state.pop(1);
690 state.push(syms.doubleType);
691 break;
692 case l2f:
693 state.pop(2);
694 state.push(syms.floatType);
695 break;
696 case l2d:
697 state.pop(2);
698 state.push(syms.doubleType);
699 break;
700 case f2i:
701 state.pop(1);
702 state.push(syms.intType);
703 break;
704 case f2l:
705 state.pop(1);
706 state.push(syms.longType);
707 break;
708 case f2d:
709 state.pop(1);
710 state.push(syms.doubleType);
711 break;
712 case d2i:
713 state.pop(2);
714 state.push(syms.intType);
715 break;
716 case d2l:
717 state.pop(2);
718 state.push(syms.longType);
719 break;
720 case d2f:
721 state.pop(2);
722 state.push(syms.floatType);
723 break;
724 case tableswitch:
725 case lookupswitch:
726 state.pop(1);
727 // the caller is responsible for patching up the state
728 break;
729 case dup_x1: {
730 Type val1 = state.pop1();
731 Type val2 = state.pop1();
732 state.push(val1);
733 state.push(val2);
734 state.push(val1);
735 break;
736 }
737 case bastore:
738 state.pop(3);
739 break;
740 case int2byte:
741 case int2char:
742 case int2short:
743 break;
744 case fmul:
745 case fadd:
746 case fsub:
747 case fdiv:
748 case fmod:
749 state.pop(1);
750 break;
751 case castore:
752 case iastore:
753 case fastore:
754 case sastore:
755 state.pop(3);
756 break;
757 case lastore:
758 case dastore:
759 state.pop(4);
760 break;
761 case dup2:
762 if (state.stack[state.stacksize-1] != null) {
763 Type value1 = state.pop1();
764 Type value2 = state.pop1();
765 state.push(value2);
766 state.push(value1);
767 state.push(value2);
768 state.push(value1);
769 } else {
770 Type value = state.pop2();
771 state.push(value);
772 state.push(value);
773 }
774 break;
775 case dup2_x1:
776 if (state.stack[state.stacksize-1] != null) {
777 Type value1 = state.pop1();
778 Type value2 = state.pop1();
779 Type value3 = state.pop1();
780 state.push(value2);
781 state.push(value1);
782 state.push(value3);
783 state.push(value2);
784 state.push(value1);
785 } else {
786 Type value1 = state.pop2();
787 Type value2 = state.pop1();
788 state.push(value1);
789 state.push(value2);
790 state.push(value1);
791 }
792 break;
793 case dup2_x2:
794 if (state.stack[state.stacksize-1] != null) {
795 Type value1 = state.pop1();
796 Type value2 = state.pop1();
797 if (state.stack[state.stacksize-1] != null) {
798 // form 1
799 Type value3 = state.pop1();
800 Type value4 = state.pop1();
801 state.push(value2);
802 state.push(value1);
803 state.push(value4);
804 state.push(value3);
805 state.push(value2);
806 state.push(value1);
807 } else {
808 // form 3
809 Type value3 = state.pop2();
810 state.push(value2);
811 state.push(value1);
812 state.push(value3);
813 state.push(value2);
814 state.push(value1);
815 }
816 } else {
817 Type value1 = state.pop2();
818 if (state.stack[state.stacksize-1] != null) {
819 // form 2
820 Type value2 = state.pop1();
821 Type value3 = state.pop1();
822 state.push(value1);
823 state.push(value3);
824 state.push(value2);
825 state.push(value1);
826 } else {
827 // form 4
828 Type value2 = state.pop2();
829 state.push(value1);
830 state.push(value2);
831 state.push(value1);
832 }
833 }
834 break;
835 case dup_x2: {
836 Type value1 = state.pop1();
837 if (state.stack[state.stacksize-1] != null) {
838 // form 1
839 Type value2 = state.pop1();
840 Type value3 = state.pop1();
841 state.push(value1);
842 state.push(value3);
843 state.push(value2);
844 state.push(value1);
845 } else {
846 // form 2
847 Type value2 = state.pop2();
848 state.push(value1);
849 state.push(value2);
850 state.push(value1);
851 }
852 }
853 break;
854 case fcmpl:
855 case fcmpg:
856 state.pop(2);
857 state.push(syms.intType);
858 break;
859 case dcmpl:
860 case dcmpg:
861 state.pop(4);
862 state.push(syms.intType);
863 break;
864 case swap: {
865 Type value1 = state.pop1();
866 Type value2 = state.pop1();
867 state.push(value1);
868 state.push(value2);
869 break;
870 }
871 case dadd:
872 case dsub:
873 case dmul:
874 case ddiv:
875 case dmod:
876 state.pop(2);
877 break;
878 case ret:
879 markDead();
880 break;
881 case wide:
882 // must be handled by the caller.
883 return;
884 case monitorenter:
885 case monitorexit:
886 state.pop(1);
887 break;
889 default:
890 throw new AssertionError(mnem(op));
891 }
892 postop();
893 }
895 /** Emit an opcode with a one-byte operand field.
896 */
897 public void emitop1(int op, int od) {
898 emitop(op);
899 if (!alive) return;
900 emit1(od);
901 switch (op) {
902 case bipush:
903 state.push(syms.intType);
904 break;
905 case ldc1:
906 state.push(typeForPool(pool.pool[od]));
907 break;
908 default:
909 throw new AssertionError(mnem(op));
910 }
911 postop();
912 }
914 /** The type of a constant pool entry. */
915 private Type typeForPool(Object o) {
916 if (o instanceof Integer) return syms.intType;
917 if (o instanceof Float) return syms.floatType;
918 if (o instanceof String) return syms.stringType;
919 if (o instanceof Long) return syms.longType;
920 if (o instanceof Double) return syms.doubleType;
921 if (o instanceof ClassSymbol) return syms.classType;
922 if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
923 if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
924 if (o instanceof Type) {
925 Type ty = ((Type)o).unannotatedType();
927 if (ty instanceof Type.ArrayType) return syms.classType;
928 if (ty instanceof Type.MethodType) return syms.methodTypeType;
929 }
930 throw new AssertionError("Invalid type of constant pool entry: " + o.getClass());
931 }
933 /** Emit an opcode with a one-byte operand field;
934 * widen if field does not fit in a byte.
935 */
936 public void emitop1w(int op, int od) {
937 if (od > 0xFF) {
938 emitop(wide);
939 emitop(op);
940 emit2(od);
941 } else {
942 emitop(op);
943 emit1(od);
944 }
945 if (!alive) return;
946 switch (op) {
947 case iload:
948 state.push(syms.intType);
949 break;
950 case lload:
951 state.push(syms.longType);
952 break;
953 case fload:
954 state.push(syms.floatType);
955 break;
956 case dload:
957 state.push(syms.doubleType);
958 break;
959 case aload:
960 state.push(lvar[od].sym.type);
961 break;
962 case lstore:
963 case dstore:
964 state.pop(2);
965 break;
966 case istore:
967 case fstore:
968 case astore:
969 state.pop(1);
970 break;
971 case ret:
972 markDead();
973 break;
974 default:
975 throw new AssertionError(mnem(op));
976 }
977 postop();
978 }
980 /** Emit an opcode with two one-byte operand fields;
981 * widen if either field does not fit in a byte.
982 */
983 public void emitop1w(int op, int od1, int od2) {
984 if (od1 > 0xFF || od2 < -128 || od2 > 127) {
985 emitop(wide);
986 emitop(op);
987 emit2(od1);
988 emit2(od2);
989 } else {
990 emitop(op);
991 emit1(od1);
992 emit1(od2);
993 }
994 if (!alive) return;
995 switch (op) {
996 case iinc:
997 break;
998 default:
999 throw new AssertionError(mnem(op));
1000 }
1001 }
1003 /** Emit an opcode with a two-byte operand field.
1004 */
1005 public void emitop2(int op, int od) {
1006 emitop(op);
1007 if (!alive) return;
1008 emit2(od);
1009 switch (op) {
1010 case getstatic:
1011 state.push(((Symbol)(pool.pool[od])).erasure(types));
1012 break;
1013 case putstatic:
1014 state.pop(((Symbol)(pool.pool[od])).erasure(types));
1015 break;
1016 case new_:
1017 Symbol sym;
1018 if (pool.pool[od] instanceof UniqueType) {
1019 // Required by change in Gen.makeRef to allow
1020 // annotated types.
1021 // TODO: is this needed anywhere else?
1022 sym = ((UniqueType)(pool.pool[od])).type.tsym;
1023 } else {
1024 sym = (Symbol)(pool.pool[od]);
1025 }
1026 state.push(uninitializedObject(sym.erasure(types), cp-3));
1027 break;
1028 case sipush:
1029 state.push(syms.intType);
1030 break;
1031 case if_acmp_null:
1032 case if_acmp_nonnull:
1033 case ifeq:
1034 case ifne:
1035 case iflt:
1036 case ifge:
1037 case ifgt:
1038 case ifle:
1039 state.pop(1);
1040 break;
1041 case if_icmpeq:
1042 case if_icmpne:
1043 case if_icmplt:
1044 case if_icmpge:
1045 case if_icmpgt:
1046 case if_icmple:
1047 case if_acmpeq:
1048 case if_acmpne:
1049 state.pop(2);
1050 break;
1051 case goto_:
1052 markDead();
1053 break;
1054 case putfield:
1055 state.pop(((Symbol)(pool.pool[od])).erasure(types));
1056 state.pop(1); // object ref
1057 break;
1058 case getfield:
1059 state.pop(1); // object ref
1060 state.push(((Symbol)(pool.pool[od])).erasure(types));
1061 break;
1062 case checkcast: {
1063 state.pop(1); // object ref
1064 Object o = pool.pool[od];
1065 Type t = (o instanceof Symbol)
1066 ? ((Symbol)o).erasure(types)
1067 : types.erasure((((UniqueType)o).type));
1068 state.push(t);
1069 break; }
1070 case ldc2w:
1071 state.push(typeForPool(pool.pool[od]));
1072 break;
1073 case instanceof_:
1074 state.pop(1);
1075 state.push(syms.intType);
1076 break;
1077 case ldc2:
1078 state.push(typeForPool(pool.pool[od]));
1079 break;
1080 case jsr:
1081 break;
1082 default:
1083 throw new AssertionError(mnem(op));
1084 }
1085 // postop();
1086 }
1088 /** Emit an opcode with a four-byte operand field.
1089 */
1090 public void emitop4(int op, int od) {
1091 emitop(op);
1092 if (!alive) return;
1093 emit4(od);
1094 switch (op) {
1095 case goto_w:
1096 markDead();
1097 break;
1098 case jsr_w:
1099 break;
1100 default:
1101 throw new AssertionError(mnem(op));
1102 }
1103 // postop();
1104 }
1106 /** Align code pointer to next `incr' boundary.
1107 */
1108 public void align(int incr) {
1109 if (alive)
1110 while (cp % incr != 0) emitop0(nop);
1111 }
1113 /** Place a byte into code at address pc.
1114 * Pre: {@literal pc + 1 <= cp }.
1115 */
1116 private void put1(int pc, int op) {
1117 code[pc] = (byte)op;
1118 }
1120 /** Place two bytes into code at address pc.
1121 * Pre: {@literal pc + 2 <= cp }.
1122 */
1123 private void put2(int pc, int od) {
1124 // pre: pc + 2 <= cp
1125 put1(pc, od >> 8);
1126 put1(pc+1, od);
1127 }
1129 /** Place four bytes into code at address pc.
1130 * Pre: {@literal pc + 4 <= cp }.
1131 */
1132 public void put4(int pc, int od) {
1133 // pre: pc + 4 <= cp
1134 put1(pc , od >> 24);
1135 put1(pc+1, od >> 16);
1136 put1(pc+2, od >> 8);
1137 put1(pc+3, od);
1138 }
1140 /** Return code byte at position pc as an unsigned int.
1141 */
1142 private int get1(int pc) {
1143 return code[pc] & 0xFF;
1144 }
1146 /** Return two code bytes at position pc as an unsigned int.
1147 */
1148 private int get2(int pc) {
1149 return (get1(pc) << 8) | get1(pc+1);
1150 }
1152 /** Return four code bytes at position pc as an int.
1153 */
1154 public int get4(int pc) {
1155 // pre: pc + 4 <= cp
1156 return
1157 (get1(pc) << 24) |
1158 (get1(pc+1) << 16) |
1159 (get1(pc+2) << 8) |
1160 (get1(pc+3));
1161 }
1163 /** Is code generation currently enabled?
1164 */
1165 public boolean isAlive() {
1166 return alive || pendingJumps != null;
1167 }
1169 /** Switch code generation on/off.
1170 */
1171 public void markDead() {
1172 alive = false;
1173 }
1175 /** Declare an entry point; return current code pointer
1176 */
1177 public int entryPoint() {
1178 int pc = curPc();
1179 alive = true;
1180 pendingStackMap = needStackMap;
1181 return pc;
1182 }
1184 /** Declare an entry point with initial state;
1185 * return current code pointer
1186 */
1187 public int entryPoint(State state) {
1188 int pc = curPc();
1189 alive = true;
1190 this.state = state.dup();
1191 Assert.check(state.stacksize <= max_stack);
1192 if (debugCode) System.err.println("entry point " + state);
1193 pendingStackMap = needStackMap;
1194 return pc;
1195 }
1197 /** Declare an entry point with initial state plus a pushed value;
1198 * return current code pointer
1199 */
1200 public int entryPoint(State state, Type pushed) {
1201 int pc = curPc();
1202 alive = true;
1203 this.state = state.dup();
1204 Assert.check(state.stacksize <= max_stack);
1205 this.state.push(pushed);
1206 if (debugCode) System.err.println("entry point " + state);
1207 pendingStackMap = needStackMap;
1208 return pc;
1209 }
1212 /**************************************************************************
1213 * Stack map generation
1214 *************************************************************************/
1216 /** An entry in the stack map. */
1217 static class StackMapFrame {
1218 int pc;
1219 Type[] locals;
1220 Type[] stack;
1221 }
1223 /** A buffer of cldc stack map entries. */
1224 StackMapFrame[] stackMapBuffer = null;
1226 /** A buffer of compressed StackMapTable entries. */
1227 StackMapTableFrame[] stackMapTableBuffer = null;
1228 int stackMapBufferSize = 0;
1230 /** The last PC at which we generated a stack map. */
1231 int lastStackMapPC = -1;
1233 /** The last stack map frame in StackMapTable. */
1234 StackMapFrame lastFrame = null;
1236 /** The stack map frame before the last one. */
1237 StackMapFrame frameBeforeLast = null;
1239 /** Emit a stack map entry. */
1240 public void emitStackMap() {
1241 int pc = curPc();
1242 if (!needStackMap) return;
1246 switch (stackMap) {
1247 case CLDC:
1248 emitCLDCStackMap(pc, getLocalsSize());
1249 break;
1250 case JSR202:
1251 emitStackMapFrame(pc, getLocalsSize());
1252 break;
1253 default:
1254 throw new AssertionError("Should have chosen a stackmap format");
1255 }
1256 // DEBUG code follows
1257 if (debugCode) state.dump(pc);
1258 }
1260 private int getLocalsSize() {
1261 int nextLocal = 0;
1262 for (int i=max_locals-1; i>=0; i--) {
1263 if (state.defined.isMember(i) && lvar[i] != null) {
1264 nextLocal = i + width(lvar[i].sym.erasure(types));
1265 break;
1266 }
1267 }
1268 return nextLocal;
1269 }
1271 /** Emit a CLDC stack map frame. */
1272 void emitCLDCStackMap(int pc, int localsSize) {
1273 if (lastStackMapPC == pc) {
1274 // drop existing stackmap at this offset
1275 stackMapBuffer[--stackMapBufferSize] = null;
1276 }
1277 lastStackMapPC = pc;
1279 if (stackMapBuffer == null) {
1280 stackMapBuffer = new StackMapFrame[20];
1281 } else {
1282 stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize);
1283 }
1284 StackMapFrame frame =
1285 stackMapBuffer[stackMapBufferSize++] = new StackMapFrame();
1286 frame.pc = pc;
1288 frame.locals = new Type[localsSize];
1289 for (int i=0; i<localsSize; i++) {
1290 if (state.defined.isMember(i) && lvar[i] != null) {
1291 Type vtype = lvar[i].sym.type;
1292 if (!(vtype instanceof UninitializedType))
1293 vtype = types.erasure(vtype);
1294 frame.locals[i] = vtype;
1295 }
1296 }
1297 frame.stack = new Type[state.stacksize];
1298 for (int i=0; i<state.stacksize; i++)
1299 frame.stack[i] = state.stack[i];
1300 }
1302 void emitStackMapFrame(int pc, int localsSize) {
1303 if (lastFrame == null) {
1304 // first frame
1305 lastFrame = getInitialFrame();
1306 } else if (lastFrame.pc == pc) {
1307 // drop existing stackmap at this offset
1308 stackMapTableBuffer[--stackMapBufferSize] = null;
1309 lastFrame = frameBeforeLast;
1310 frameBeforeLast = null;
1311 }
1313 StackMapFrame frame = new StackMapFrame();
1314 frame.pc = pc;
1316 int localCount = 0;
1317 Type[] locals = new Type[localsSize];
1318 for (int i=0; i<localsSize; i++, localCount++) {
1319 if (state.defined.isMember(i) && lvar[i] != null) {
1320 Type vtype = lvar[i].sym.type;
1321 if (!(vtype instanceof UninitializedType))
1322 vtype = types.erasure(vtype);
1323 locals[i] = vtype;
1324 if (width(vtype) > 1) i++;
1325 }
1326 }
1327 frame.locals = new Type[localCount];
1328 for (int i=0, j=0; i<localsSize; i++, j++) {
1329 Assert.check(j < localCount);
1330 frame.locals[j] = locals[i];
1331 if (width(locals[i]) > 1) i++;
1332 }
1334 int stackCount = 0;
1335 for (int i=0; i<state.stacksize; i++) {
1336 if (state.stack[i] != null) {
1337 stackCount++;
1338 }
1339 }
1340 frame.stack = new Type[stackCount];
1341 stackCount = 0;
1342 for (int i=0; i<state.stacksize; i++) {
1343 if (state.stack[i] != null) {
1344 frame.stack[stackCount++] = types.erasure(state.stack[i]);
1345 }
1346 }
1348 if (stackMapTableBuffer == null) {
1349 stackMapTableBuffer = new StackMapTableFrame[20];
1350 } else {
1351 stackMapTableBuffer = ArrayUtils.ensureCapacity(
1352 stackMapTableBuffer,
1353 stackMapBufferSize);
1354 }
1355 stackMapTableBuffer[stackMapBufferSize++] =
1356 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
1358 frameBeforeLast = lastFrame;
1359 lastFrame = frame;
1360 }
1362 StackMapFrame getInitialFrame() {
1363 StackMapFrame frame = new StackMapFrame();
1364 List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes;
1365 int len = arg_types.length();
1366 int count = 0;
1367 if (!meth.isStatic()) {
1368 Type thisType = meth.owner.type;
1369 frame.locals = new Type[len+1];
1370 if (meth.isConstructor() && thisType != syms.objectType) {
1371 frame.locals[count++] = UninitializedType.uninitializedThis(thisType);
1372 } else {
1373 frame.locals[count++] = types.erasure(thisType);
1374 }
1375 } else {
1376 frame.locals = new Type[len];
1377 }
1378 for (Type arg_type : arg_types) {
1379 frame.locals[count++] = types.erasure(arg_type);
1380 }
1381 frame.pc = -1;
1382 frame.stack = null;
1383 return frame;
1384 }
1387 /**************************************************************************
1388 * Operations having to do with jumps
1389 *************************************************************************/
1391 /** A chain represents a list of unresolved jumps. Jump locations
1392 * are sorted in decreasing order.
1393 */
1394 public static class Chain {
1396 /** The position of the jump instruction.
1397 */
1398 public final int pc;
1400 /** The machine state after the jump instruction.
1401 * Invariant: all elements of a chain list have the same stacksize
1402 * and compatible stack and register contents.
1403 */
1404 Code.State state;
1406 /** The next jump in the list.
1407 */
1408 public final Chain next;
1410 /** Construct a chain from its jump position, stacksize, previous
1411 * chain, and machine state.
1412 */
1413 public Chain(int pc, Chain next, Code.State state) {
1414 this.pc = pc;
1415 this.next = next;
1416 this.state = state;
1417 }
1418 }
1420 /** Negate a branch opcode.
1421 */
1422 public static int negate(int opcode) {
1423 if (opcode == if_acmp_null) return if_acmp_nonnull;
1424 else if (opcode == if_acmp_nonnull) return if_acmp_null;
1425 else return ((opcode + 1) ^ 1) - 1;
1426 }
1428 /** Emit a jump instruction.
1429 * Return code pointer of instruction to be patched.
1430 */
1431 public int emitJump(int opcode) {
1432 if (fatcode) {
1433 if (opcode == goto_ || opcode == jsr) {
1434 emitop4(opcode + goto_w - goto_, 0);
1435 } else {
1436 emitop2(negate(opcode), 8);
1437 emitop4(goto_w, 0);
1438 alive = true;
1439 pendingStackMap = needStackMap;
1440 }
1441 return cp - 5;
1442 } else {
1443 emitop2(opcode, 0);
1444 return cp - 3;
1445 }
1446 }
1448 /** Emit a branch with given opcode; return its chain.
1449 * branch differs from jump in that jsr is treated as no-op.
1450 */
1451 public Chain branch(int opcode) {
1452 Chain result = null;
1453 if (opcode == goto_) {
1454 result = pendingJumps;
1455 pendingJumps = null;
1456 }
1457 if (opcode != dontgoto && isAlive()) {
1458 result = new Chain(emitJump(opcode),
1459 result,
1460 state.dup());
1461 fixedPc = fatcode;
1462 if (opcode == goto_) alive = false;
1463 }
1464 return result;
1465 }
1467 /** Resolve chain to point to given target.
1468 */
1469 public void resolve(Chain chain, int target) {
1470 boolean changed = false;
1471 State newState = state;
1472 for (; chain != null; chain = chain.next) {
1473 Assert.check(state != chain.state
1474 && (target > chain.pc || state.stacksize == 0));
1475 if (target >= cp) {
1476 target = cp;
1477 } else if (get1(target) == goto_) {
1478 if (fatcode) target = target + get4(target + 1);
1479 else target = target + get2(target + 1);
1480 }
1481 if (get1(chain.pc) == goto_ &&
1482 chain.pc + 3 == target && target == cp && !fixedPc) {
1483 // If goto the next instruction, the jump is not needed:
1484 // compact the code.
1485 cp = cp - 3;
1486 target = target - 3;
1487 if (chain.next == null) {
1488 // This is the only jump to the target. Exit the loop
1489 // without setting new state. The code is reachable
1490 // from the instruction before goto_.
1491 alive = true;
1492 break;
1493 }
1494 } else {
1495 if (fatcode)
1496 put4(chain.pc + 1, target - chain.pc);
1497 else if (target - chain.pc < Short.MIN_VALUE ||
1498 target - chain.pc > Short.MAX_VALUE)
1499 fatcode = true;
1500 else
1501 put2(chain.pc + 1, target - chain.pc);
1502 Assert.check(!alive ||
1503 chain.state.stacksize == newState.stacksize &&
1504 chain.state.nlocks == newState.nlocks);
1505 }
1506 fixedPc = true;
1507 if (cp == target) {
1508 changed = true;
1509 if (debugCode)
1510 System.err.println("resolving chain state=" + chain.state);
1511 if (alive) {
1512 newState = chain.state.join(newState);
1513 } else {
1514 newState = chain.state;
1515 alive = true;
1516 }
1517 }
1518 }
1519 Assert.check(!changed || state != newState);
1520 if (state != newState) {
1521 setDefined(newState.defined);
1522 state = newState;
1523 pendingStackMap = needStackMap;
1524 }
1525 }
1527 /** Resolve chain to point to current code pointer.
1528 */
1529 public void resolve(Chain chain) {
1530 Assert.check(
1531 !alive ||
1532 chain==null ||
1533 state.stacksize == chain.state.stacksize &&
1534 state.nlocks == chain.state.nlocks);
1535 pendingJumps = mergeChains(chain, pendingJumps);
1536 }
1538 /** Resolve any pending jumps.
1539 */
1540 public void resolvePending() {
1541 Chain x = pendingJumps;
1542 pendingJumps = null;
1543 resolve(x, cp);
1544 }
1546 /** Merge the jumps in of two chains into one.
1547 */
1548 public static Chain mergeChains(Chain chain1, Chain chain2) {
1549 // recursive merge sort
1550 if (chain2 == null) return chain1;
1551 if (chain1 == null) return chain2;
1552 Assert.check(
1553 chain1.state.stacksize == chain2.state.stacksize &&
1554 chain1.state.nlocks == chain2.state.nlocks);
1555 if (chain1.pc < chain2.pc)
1556 return new Chain(
1557 chain2.pc,
1558 mergeChains(chain1, chain2.next),
1559 chain2.state);
1560 return new Chain(
1561 chain1.pc,
1562 mergeChains(chain1.next, chain2),
1563 chain1.state);
1564 }
1567 /* **************************************************************************
1568 * Catch clauses
1569 ****************************************************************************/
1571 /** Add a catch clause to code.
1572 */
1573 public void addCatch(
1574 char startPc, char endPc, char handlerPc, char catchType) {
1575 catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType});
1576 }
1579 public void compressCatchTable() {
1580 ListBuffer<char[]> compressedCatchInfo = ListBuffer.lb();
1581 List<Integer> handlerPcs = List.nil();
1582 for (char[] catchEntry : catchInfo) {
1583 handlerPcs = handlerPcs.prepend((int)catchEntry[2]);
1584 }
1585 for (char[] catchEntry : catchInfo) {
1586 int startpc = catchEntry[0];
1587 int endpc = catchEntry[1];
1588 if (startpc == endpc ||
1589 (startpc == (endpc - 1) &&
1590 handlerPcs.contains(startpc))) {
1591 continue;
1592 } else {
1593 compressedCatchInfo.append(catchEntry);
1594 }
1595 }
1596 catchInfo = compressedCatchInfo;
1597 }
1600 /* **************************************************************************
1601 * Line numbers
1602 ****************************************************************************/
1604 /** Add a line number entry.
1605 */
1606 public void addLineNumber(char startPc, char lineNumber) {
1607 if (lineDebugInfo) {
1608 if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc)
1609 lineInfo = lineInfo.tail;
1610 if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber)
1611 lineInfo = lineInfo.prepend(new char[]{startPc, lineNumber});
1612 }
1613 }
1615 /** Mark beginning of statement.
1616 */
1617 public void statBegin(int pos) {
1618 if (pos != Position.NOPOS) {
1619 pendingStatPos = pos;
1620 }
1621 }
1623 /** Force stat begin eagerly
1624 */
1625 public void markStatBegin() {
1626 if (alive && lineDebugInfo) {
1627 int line = lineMap.getLineNumber(pendingStatPos);
1628 char cp1 = (char)cp;
1629 char line1 = (char)line;
1630 if (cp1 == cp && line1 == line)
1631 addLineNumber(cp1, line1);
1632 }
1633 pendingStatPos = Position.NOPOS;
1634 }
1637 /* **************************************************************************
1638 * Simulated VM machine state
1639 ****************************************************************************/
1641 class State implements Cloneable {
1642 /** The set of registers containing values. */
1643 Bits defined;
1645 /** The (types of the) contents of the machine stack. */
1646 Type[] stack;
1648 /** The first stack position currently unused. */
1649 int stacksize;
1651 /** The numbers of registers containing locked monitors. */
1652 int[] locks;
1653 int nlocks;
1655 State() {
1656 defined = new Bits();
1657 stack = new Type[16];
1658 }
1660 State dup() {
1661 try {
1662 State state = (State)super.clone();
1663 state.defined = new Bits(defined);
1664 state.stack = stack.clone();
1665 if (locks != null) state.locks = locks.clone();
1666 if (debugCode) {
1667 System.err.println("duping state " + this);
1668 dump();
1669 }
1670 return state;
1671 } catch (CloneNotSupportedException ex) {
1672 throw new AssertionError(ex);
1673 }
1674 }
1676 void lock(int register) {
1677 if (locks == null) {
1678 locks = new int[20];
1679 } else {
1680 locks = ArrayUtils.ensureCapacity(locks, nlocks);
1681 }
1682 locks[nlocks] = register;
1683 nlocks++;
1684 }
1686 void unlock(int register) {
1687 nlocks--;
1688 Assert.check(locks[nlocks] == register);
1689 locks[nlocks] = -1;
1690 }
1692 void push(Type t) {
1693 if (debugCode) System.err.println(" pushing " + t);
1694 switch (t.getTag()) {
1695 case VOID:
1696 return;
1697 case BYTE:
1698 case CHAR:
1699 case SHORT:
1700 case BOOLEAN:
1701 t = syms.intType;
1702 break;
1703 default:
1704 break;
1705 }
1706 stack = ArrayUtils.ensureCapacity(stack, stacksize+2);
1707 stack[stacksize++] = t;
1708 switch (width(t)) {
1709 case 1:
1710 break;
1711 case 2:
1712 stack[stacksize++] = null;
1713 break;
1714 default:
1715 throw new AssertionError(t);
1716 }
1717 if (stacksize > max_stack)
1718 max_stack = stacksize;
1719 }
1721 Type pop1() {
1722 if (debugCode) System.err.println(" popping " + 1);
1723 stacksize--;
1724 Type result = stack[stacksize];
1725 stack[stacksize] = null;
1726 Assert.check(result != null && width(result) == 1);
1727 return result;
1728 }
1730 Type peek() {
1731 return stack[stacksize-1];
1732 }
1734 Type pop2() {
1735 if (debugCode) System.err.println(" popping " + 2);
1736 stacksize -= 2;
1737 Type result = stack[stacksize];
1738 stack[stacksize] = null;
1739 Assert.check(stack[stacksize+1] == null
1740 && result != null && width(result) == 2);
1741 return result;
1742 }
1744 void pop(int n) {
1745 if (debugCode) System.err.println(" popping " + n);
1746 while (n > 0) {
1747 stack[--stacksize] = null;
1748 n--;
1749 }
1750 }
1752 void pop(Type t) {
1753 pop(width(t));
1754 }
1756 /** Force the top of the stack to be treated as this supertype
1757 * of its current type. */
1758 void forceStackTop(Type t) {
1759 if (!alive) return;
1760 switch (t.getTag()) {
1761 case CLASS:
1762 case ARRAY:
1763 int width = width(t);
1764 Type old = stack[stacksize-width];
1765 Assert.check(types.isSubtype(types.erasure(old),
1766 types.erasure(t)));
1767 stack[stacksize-width] = t;
1768 break;
1769 default:
1770 }
1771 }
1773 void markInitialized(UninitializedType old) {
1774 Type newtype = old.initializedType();
1775 for (int i=0; i<stacksize; i++)
1776 if (stack[i] == old) stack[i] = newtype;
1777 for (int i=0; i<lvar.length; i++) {
1778 LocalVar lv = lvar[i];
1779 if (lv != null && lv.sym.type == old) {
1780 VarSymbol sym = lv.sym;
1781 sym = sym.clone(sym.owner);
1782 sym.type = newtype;
1783 LocalVar newlv = lvar[i] = new LocalVar(sym);
1784 // should the following be initialized to cp?
1785 newlv.start_pc = lv.start_pc;
1786 }
1787 }
1788 }
1790 State join(State other) {
1791 defined.andSet(other.defined);
1792 Assert.check(stacksize == other.stacksize
1793 && nlocks == other.nlocks);
1794 for (int i=0; i<stacksize; ) {
1795 Type t = stack[i];
1796 Type tother = other.stack[i];
1797 Type result =
1798 t==tother ? t :
1799 types.isSubtype(t, tother) ? tother :
1800 types.isSubtype(tother, t) ? t :
1801 error();
1802 int w = width(result);
1803 stack[i] = result;
1804 if (w == 2) Assert.checkNull(stack[i+1]);
1805 i += w;
1806 }
1807 return this;
1808 }
1810 Type error() {
1811 throw new AssertionError("inconsistent stack types at join point");
1812 }
1814 void dump() {
1815 dump(-1);
1816 }
1818 void dump(int pc) {
1819 System.err.print("stackMap for " + meth.owner + "." + meth);
1820 if (pc == -1)
1821 System.out.println();
1822 else
1823 System.out.println(" at " + pc);
1824 System.err.println(" stack (from bottom):");
1825 for (int i=0; i<stacksize; i++)
1826 System.err.println(" " + i + ": " + stack[i]);
1828 int lastLocal = 0;
1829 for (int i=max_locals-1; i>=0; i--) {
1830 if (defined.isMember(i)) {
1831 lastLocal = i;
1832 break;
1833 }
1834 }
1835 if (lastLocal >= 0)
1836 System.err.println(" locals:");
1837 for (int i=0; i<=lastLocal; i++) {
1838 System.err.print(" " + i + ": ");
1839 if (defined.isMember(i)) {
1840 LocalVar var = lvar[i];
1841 if (var == null) {
1842 System.err.println("(none)");
1843 } else if (var.sym == null)
1844 System.err.println("UNKNOWN!");
1845 else
1846 System.err.println("" + var.sym + " of type " +
1847 var.sym.erasure(types));
1848 } else {
1849 System.err.println("undefined");
1850 }
1851 }
1852 if (nlocks != 0) {
1853 System.err.print(" locks:");
1854 for (int i=0; i<nlocks; i++) {
1855 System.err.print(" " + locks[i]);
1856 }
1857 System.err.println();
1858 }
1859 }
1860 }
1862 static final Type jsrReturnValue = new JCPrimitiveType(INT, null);
1865 /* **************************************************************************
1866 * Local variables
1867 ****************************************************************************/
1869 /** A live range of a local variable. */
1870 static class LocalVar {
1871 final VarSymbol sym;
1872 final char reg;
1873 char start_pc = Character.MAX_VALUE;
1874 char length = Character.MAX_VALUE;
1875 LocalVar(VarSymbol v) {
1876 this.sym = v;
1877 this.reg = (char)v.adr;
1878 }
1879 public LocalVar dup() {
1880 return new LocalVar(sym);
1881 }
1882 public String toString() {
1883 return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length);
1884 }
1885 };
1887 /** Local variables, indexed by register. */
1888 LocalVar[] lvar;
1890 /** Add a new local variable. */
1891 private void addLocalVar(VarSymbol v) {
1892 int adr = v.adr;
1893 lvar = ArrayUtils.ensureCapacity(lvar, adr+1);
1894 Assert.checkNull(lvar[adr]);
1895 if (pendingJumps != null) resolvePending();
1896 lvar[adr] = new LocalVar(v);
1897 state.defined.excl(adr);
1898 }
1900 /** Set the current variable defined state. */
1901 public void setDefined(Bits newDefined) {
1902 if (alive && newDefined != state.defined) {
1903 Bits diff = new Bits(state.defined).xorSet(newDefined);
1904 for (int adr = diff.nextBit(0);
1905 adr >= 0;
1906 adr = diff.nextBit(adr+1)) {
1907 if (adr >= nextreg)
1908 state.defined.excl(adr);
1909 else if (state.defined.isMember(adr))
1910 setUndefined(adr);
1911 else
1912 setDefined(adr);
1913 }
1914 }
1915 }
1917 /** Mark a register as being (possibly) defined. */
1918 public void setDefined(int adr) {
1919 LocalVar v = lvar[adr];
1920 if (v == null) {
1921 state.defined.excl(adr);
1922 } else {
1923 state.defined.incl(adr);
1924 if (cp < Character.MAX_VALUE) {
1925 if (v.start_pc == Character.MAX_VALUE)
1926 v.start_pc = (char)cp;
1927 }
1928 }
1929 }
1931 /** Mark a register as being undefined. */
1932 public void setUndefined(int adr) {
1933 state.defined.excl(adr);
1934 if (adr < lvar.length &&
1935 lvar[adr] != null &&
1936 lvar[adr].start_pc != Character.MAX_VALUE) {
1937 LocalVar v = lvar[adr];
1938 char length = (char)(curPc() - v.start_pc);
1939 if (length > 0 && length < Character.MAX_VALUE) {
1940 lvar[adr] = v.dup();
1941 v.length = length;
1942 putVar(v);
1943 } else {
1944 v.start_pc = Character.MAX_VALUE;
1945 }
1946 }
1947 }
1949 /** End the scope of a variable. */
1950 private void endScope(int adr) {
1951 LocalVar v = lvar[adr];
1952 if (v != null) {
1953 lvar[adr] = null;
1954 if (v.start_pc != Character.MAX_VALUE) {
1955 char length = (char)(curPc() - v.start_pc);
1956 if (length < Character.MAX_VALUE) {
1957 v.length = length;
1958 putVar(v);
1959 fillLocalVarPosition(v);
1960 }
1961 }
1962 }
1963 state.defined.excl(adr);
1964 }
1966 private void fillLocalVarPosition(LocalVar lv) {
1967 if (lv == null || lv.sym == null || !lv.sym.hasTypeAnnotations())
1968 return;
1969 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
1970 TypeAnnotationPosition p = ta.position;
1971 p.lvarOffset = new int[] { (int)lv.start_pc };
1972 p.lvarLength = new int[] { (int)lv.length };
1973 p.lvarIndex = new int[] { (int)lv.reg };
1974 p.isValidOffset = true;
1975 }
1976 }
1978 // Method to be called after compressCatchTable to
1979 // fill in the exception table index for type
1980 // annotations on exception parameters.
1981 public void fillExceptionParameterPositions() {
1982 for (int i = 0; i < varBufferSize; ++i) {
1983 LocalVar lv = varBuffer[i];
1984 if (lv == null || lv.sym == null
1985 || !lv.sym.hasTypeAnnotations()
1986 || !lv.sym.isExceptionParameter())
1987 continue;
1989 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
1990 TypeAnnotationPosition p = ta.position;
1991 // At this point p.type_index contains the catch type index.
1992 // Use that index to determine the exception table index.
1993 // We can afterwards discard the type_index.
1994 // A TA position is shared for all type annotations in the
1995 // same location; updating one is enough.
1996 // Use -666 as a marker that the exception_index was already updated.
1997 if (p.type_index != -666) {
1998 p.exception_index = findExceptionIndex(p.type_index);
1999 p.type_index = -666;
2000 }
2001 }
2002 }
2003 }
2005 private int findExceptionIndex(int catchType) {
2006 if (catchType == Integer.MIN_VALUE) {
2007 // We didn't set the catch type index correctly.
2008 // This shouldn't happen.
2009 // TODO: issue error?
2010 return -1;
2011 }
2012 List<char[]> iter = catchInfo.toList();
2013 int len = catchInfo.length();
2014 for (int i = 0; i < len; ++i) {
2015 char[] catchEntry = iter.head;
2016 iter = iter.tail;
2017 char ct = catchEntry[3];
2018 if (catchType == ct) {
2019 return i;
2020 }
2021 }
2022 return -1;
2023 }
2025 /** Put a live variable range into the buffer to be output to the
2026 * class file.
2027 */
2028 void putVar(LocalVar var) {
2029 // Keep local variables if
2030 // 1) we need them for debug information
2031 // 2) it is an exception type and it contains type annotations
2032 if (!varDebugInfo &&
2033 (!var.sym.isExceptionParameter() ||
2034 var.sym.hasTypeAnnotations())) return;
2035 if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
2036 if (varBuffer == null)
2037 varBuffer = new LocalVar[20];
2038 else
2039 varBuffer = ArrayUtils.ensureCapacity(varBuffer, varBufferSize);
2040 varBuffer[varBufferSize++] = var;
2041 }
2043 /** Previously live local variables, to be put into the variable table. */
2044 LocalVar[] varBuffer;
2045 int varBufferSize;
2047 /** Create a new local variable address and return it.
2048 */
2049 private int newLocal(int typecode) {
2050 int reg = nextreg;
2051 int w = width(typecode);
2052 nextreg = reg + w;
2053 if (nextreg > max_locals) max_locals = nextreg;
2054 return reg;
2055 }
2057 private int newLocal(Type type) {
2058 return newLocal(typecode(type));
2059 }
2061 public int newLocal(VarSymbol v) {
2062 int reg = v.adr = newLocal(v.erasure(types));
2063 addLocalVar(v);
2064 return reg;
2065 }
2067 /** Start a set of fresh registers.
2068 */
2069 public void newRegSegment() {
2070 nextreg = max_locals;
2071 }
2073 /** End scopes of all variables with registers ≥ first.
2074 */
2075 public void endScopes(int first) {
2076 int prevNextReg = nextreg;
2077 nextreg = first;
2078 for (int i = nextreg; i < prevNextReg; i++) endScope(i);
2079 }
2081 /**************************************************************************
2082 * static tables
2083 *************************************************************************/
2085 public static String mnem(int opcode) {
2086 return Mneumonics.mnem[opcode];
2087 }
2089 private static class Mneumonics {
2090 private final static String[] mnem = new String[ByteCodeCount];
2091 static {
2092 mnem[nop] = "nop";
2093 mnem[aconst_null] = "aconst_null";
2094 mnem[iconst_m1] = "iconst_m1";
2095 mnem[iconst_0] = "iconst_0";
2096 mnem[iconst_1] = "iconst_1";
2097 mnem[iconst_2] = "iconst_2";
2098 mnem[iconst_3] = "iconst_3";
2099 mnem[iconst_4] = "iconst_4";
2100 mnem[iconst_5] = "iconst_5";
2101 mnem[lconst_0] = "lconst_0";
2102 mnem[lconst_1] = "lconst_1";
2103 mnem[fconst_0] = "fconst_0";
2104 mnem[fconst_1] = "fconst_1";
2105 mnem[fconst_2] = "fconst_2";
2106 mnem[dconst_0] = "dconst_0";
2107 mnem[dconst_1] = "dconst_1";
2108 mnem[bipush] = "bipush";
2109 mnem[sipush] = "sipush";
2110 mnem[ldc1] = "ldc1";
2111 mnem[ldc2] = "ldc2";
2112 mnem[ldc2w] = "ldc2w";
2113 mnem[iload] = "iload";
2114 mnem[lload] = "lload";
2115 mnem[fload] = "fload";
2116 mnem[dload] = "dload";
2117 mnem[aload] = "aload";
2118 mnem[iload_0] = "iload_0";
2119 mnem[lload_0] = "lload_0";
2120 mnem[fload_0] = "fload_0";
2121 mnem[dload_0] = "dload_0";
2122 mnem[aload_0] = "aload_0";
2123 mnem[iload_1] = "iload_1";
2124 mnem[lload_1] = "lload_1";
2125 mnem[fload_1] = "fload_1";
2126 mnem[dload_1] = "dload_1";
2127 mnem[aload_1] = "aload_1";
2128 mnem[iload_2] = "iload_2";
2129 mnem[lload_2] = "lload_2";
2130 mnem[fload_2] = "fload_2";
2131 mnem[dload_2] = "dload_2";
2132 mnem[aload_2] = "aload_2";
2133 mnem[iload_3] = "iload_3";
2134 mnem[lload_3] = "lload_3";
2135 mnem[fload_3] = "fload_3";
2136 mnem[dload_3] = "dload_3";
2137 mnem[aload_3] = "aload_3";
2138 mnem[iaload] = "iaload";
2139 mnem[laload] = "laload";
2140 mnem[faload] = "faload";
2141 mnem[daload] = "daload";
2142 mnem[aaload] = "aaload";
2143 mnem[baload] = "baload";
2144 mnem[caload] = "caload";
2145 mnem[saload] = "saload";
2146 mnem[istore] = "istore";
2147 mnem[lstore] = "lstore";
2148 mnem[fstore] = "fstore";
2149 mnem[dstore] = "dstore";
2150 mnem[astore] = "astore";
2151 mnem[istore_0] = "istore_0";
2152 mnem[lstore_0] = "lstore_0";
2153 mnem[fstore_0] = "fstore_0";
2154 mnem[dstore_0] = "dstore_0";
2155 mnem[astore_0] = "astore_0";
2156 mnem[istore_1] = "istore_1";
2157 mnem[lstore_1] = "lstore_1";
2158 mnem[fstore_1] = "fstore_1";
2159 mnem[dstore_1] = "dstore_1";
2160 mnem[astore_1] = "astore_1";
2161 mnem[istore_2] = "istore_2";
2162 mnem[lstore_2] = "lstore_2";
2163 mnem[fstore_2] = "fstore_2";
2164 mnem[dstore_2] = "dstore_2";
2165 mnem[astore_2] = "astore_2";
2166 mnem[istore_3] = "istore_3";
2167 mnem[lstore_3] = "lstore_3";
2168 mnem[fstore_3] = "fstore_3";
2169 mnem[dstore_3] = "dstore_3";
2170 mnem[astore_3] = "astore_3";
2171 mnem[iastore] = "iastore";
2172 mnem[lastore] = "lastore";
2173 mnem[fastore] = "fastore";
2174 mnem[dastore] = "dastore";
2175 mnem[aastore] = "aastore";
2176 mnem[bastore] = "bastore";
2177 mnem[castore] = "castore";
2178 mnem[sastore] = "sastore";
2179 mnem[pop] = "pop";
2180 mnem[pop2] = "pop2";
2181 mnem[dup] = "dup";
2182 mnem[dup_x1] = "dup_x1";
2183 mnem[dup_x2] = "dup_x2";
2184 mnem[dup2] = "dup2";
2185 mnem[dup2_x1] = "dup2_x1";
2186 mnem[dup2_x2] = "dup2_x2";
2187 mnem[swap] = "swap";
2188 mnem[iadd] = "iadd";
2189 mnem[ladd] = "ladd";
2190 mnem[fadd] = "fadd";
2191 mnem[dadd] = "dadd";
2192 mnem[isub] = "isub";
2193 mnem[lsub] = "lsub";
2194 mnem[fsub] = "fsub";
2195 mnem[dsub] = "dsub";
2196 mnem[imul] = "imul";
2197 mnem[lmul] = "lmul";
2198 mnem[fmul] = "fmul";
2199 mnem[dmul] = "dmul";
2200 mnem[idiv] = "idiv";
2201 mnem[ldiv] = "ldiv";
2202 mnem[fdiv] = "fdiv";
2203 mnem[ddiv] = "ddiv";
2204 mnem[imod] = "imod";
2205 mnem[lmod] = "lmod";
2206 mnem[fmod] = "fmod";
2207 mnem[dmod] = "dmod";
2208 mnem[ineg] = "ineg";
2209 mnem[lneg] = "lneg";
2210 mnem[fneg] = "fneg";
2211 mnem[dneg] = "dneg";
2212 mnem[ishl] = "ishl";
2213 mnem[lshl] = "lshl";
2214 mnem[ishr] = "ishr";
2215 mnem[lshr] = "lshr";
2216 mnem[iushr] = "iushr";
2217 mnem[lushr] = "lushr";
2218 mnem[iand] = "iand";
2219 mnem[land] = "land";
2220 mnem[ior] = "ior";
2221 mnem[lor] = "lor";
2222 mnem[ixor] = "ixor";
2223 mnem[lxor] = "lxor";
2224 mnem[iinc] = "iinc";
2225 mnem[i2l] = "i2l";
2226 mnem[i2f] = "i2f";
2227 mnem[i2d] = "i2d";
2228 mnem[l2i] = "l2i";
2229 mnem[l2f] = "l2f";
2230 mnem[l2d] = "l2d";
2231 mnem[f2i] = "f2i";
2232 mnem[f2l] = "f2l";
2233 mnem[f2d] = "f2d";
2234 mnem[d2i] = "d2i";
2235 mnem[d2l] = "d2l";
2236 mnem[d2f] = "d2f";
2237 mnem[int2byte] = "int2byte";
2238 mnem[int2char] = "int2char";
2239 mnem[int2short] = "int2short";
2240 mnem[lcmp] = "lcmp";
2241 mnem[fcmpl] = "fcmpl";
2242 mnem[fcmpg] = "fcmpg";
2243 mnem[dcmpl] = "dcmpl";
2244 mnem[dcmpg] = "dcmpg";
2245 mnem[ifeq] = "ifeq";
2246 mnem[ifne] = "ifne";
2247 mnem[iflt] = "iflt";
2248 mnem[ifge] = "ifge";
2249 mnem[ifgt] = "ifgt";
2250 mnem[ifle] = "ifle";
2251 mnem[if_icmpeq] = "if_icmpeq";
2252 mnem[if_icmpne] = "if_icmpne";
2253 mnem[if_icmplt] = "if_icmplt";
2254 mnem[if_icmpge] = "if_icmpge";
2255 mnem[if_icmpgt] = "if_icmpgt";
2256 mnem[if_icmple] = "if_icmple";
2257 mnem[if_acmpeq] = "if_acmpeq";
2258 mnem[if_acmpne] = "if_acmpne";
2259 mnem[goto_] = "goto_";
2260 mnem[jsr] = "jsr";
2261 mnem[ret] = "ret";
2262 mnem[tableswitch] = "tableswitch";
2263 mnem[lookupswitch] = "lookupswitch";
2264 mnem[ireturn] = "ireturn";
2265 mnem[lreturn] = "lreturn";
2266 mnem[freturn] = "freturn";
2267 mnem[dreturn] = "dreturn";
2268 mnem[areturn] = "areturn";
2269 mnem[return_] = "return_";
2270 mnem[getstatic] = "getstatic";
2271 mnem[putstatic] = "putstatic";
2272 mnem[getfield] = "getfield";
2273 mnem[putfield] = "putfield";
2274 mnem[invokevirtual] = "invokevirtual";
2275 mnem[invokespecial] = "invokespecial";
2276 mnem[invokestatic] = "invokestatic";
2277 mnem[invokeinterface] = "invokeinterface";
2278 mnem[invokedynamic] = "invokedynamic";
2279 mnem[new_] = "new_";
2280 mnem[newarray] = "newarray";
2281 mnem[anewarray] = "anewarray";
2282 mnem[arraylength] = "arraylength";
2283 mnem[athrow] = "athrow";
2284 mnem[checkcast] = "checkcast";
2285 mnem[instanceof_] = "instanceof_";
2286 mnem[monitorenter] = "monitorenter";
2287 mnem[monitorexit] = "monitorexit";
2288 mnem[wide] = "wide";
2289 mnem[multianewarray] = "multianewarray";
2290 mnem[if_acmp_null] = "if_acmp_null";
2291 mnem[if_acmp_nonnull] = "if_acmp_nonnull";
2292 mnem[goto_w] = "goto_w";
2293 mnem[jsr_w] = "jsr_w";
2294 mnem[breakpoint] = "breakpoint";
2295 }
2296 }
2297 }