Tue, 02 Apr 2013 10:51:16 +0100
4965689: class literal code wastes a byte
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 emitop(invokedynamic);
474 if (!alive) return;
475 emit2(desc);
476 emit2(0);
477 state.pop(argsize);
478 state.push(mtype.getReturnType());
479 }
481 /** Emit an opcode with no operand field.
482 */
483 public void emitop0(int op) {
484 emitop(op);
485 if (!alive) return;
486 switch (op) {
487 case aaload: {
488 state.pop(1);// index
489 Type a = state.stack[state.stacksize-1];
490 state.pop(1);
491 //sometimes 'null type' is treated as a one-dimensional array type
492 //see Gen.visitLiteral - we should handle this case accordingly
493 Type stackType = a.hasTag(BOT) ?
494 syms.objectType :
495 types.erasure(types.elemtype(a));
496 state.push(stackType); }
497 break;
498 case goto_:
499 markDead();
500 break;
501 case nop:
502 case ineg:
503 case lneg:
504 case fneg:
505 case dneg:
506 break;
507 case aconst_null:
508 state.push(syms.botType);
509 break;
510 case iconst_m1:
511 case iconst_0:
512 case iconst_1:
513 case iconst_2:
514 case iconst_3:
515 case iconst_4:
516 case iconst_5:
517 case iload_0:
518 case iload_1:
519 case iload_2:
520 case iload_3:
521 state.push(syms.intType);
522 break;
523 case lconst_0:
524 case lconst_1:
525 case lload_0:
526 case lload_1:
527 case lload_2:
528 case lload_3:
529 state.push(syms.longType);
530 break;
531 case fconst_0:
532 case fconst_1:
533 case fconst_2:
534 case fload_0:
535 case fload_1:
536 case fload_2:
537 case fload_3:
538 state.push(syms.floatType);
539 break;
540 case dconst_0:
541 case dconst_1:
542 case dload_0:
543 case dload_1:
544 case dload_2:
545 case dload_3:
546 state.push(syms.doubleType);
547 break;
548 case aload_0:
549 state.push(lvar[0].sym.type);
550 break;
551 case aload_1:
552 state.push(lvar[1].sym.type);
553 break;
554 case aload_2:
555 state.push(lvar[2].sym.type);
556 break;
557 case aload_3:
558 state.push(lvar[3].sym.type);
559 break;
560 case iaload:
561 case baload:
562 case caload:
563 case saload:
564 state.pop(2);
565 state.push(syms.intType);
566 break;
567 case laload:
568 state.pop(2);
569 state.push(syms.longType);
570 break;
571 case faload:
572 state.pop(2);
573 state.push(syms.floatType);
574 break;
575 case daload:
576 state.pop(2);
577 state.push(syms.doubleType);
578 break;
579 case istore_0:
580 case istore_1:
581 case istore_2:
582 case istore_3:
583 case fstore_0:
584 case fstore_1:
585 case fstore_2:
586 case fstore_3:
587 case astore_0:
588 case astore_1:
589 case astore_2:
590 case astore_3:
591 case pop:
592 case lshr:
593 case lshl:
594 case lushr:
595 state.pop(1);
596 break;
597 case areturn:
598 case ireturn:
599 case freturn:
600 Assert.check(state.nlocks == 0);
601 state.pop(1);
602 markDead();
603 break;
604 case athrow:
605 state.pop(1);
606 markDead();
607 break;
608 case lstore_0:
609 case lstore_1:
610 case lstore_2:
611 case lstore_3:
612 case dstore_0:
613 case dstore_1:
614 case dstore_2:
615 case dstore_3:
616 case pop2:
617 state.pop(2);
618 break;
619 case lreturn:
620 case dreturn:
621 Assert.check(state.nlocks == 0);
622 state.pop(2);
623 markDead();
624 break;
625 case dup:
626 state.push(state.stack[state.stacksize-1]);
627 break;
628 case return_:
629 Assert.check(state.nlocks == 0);
630 markDead();
631 break;
632 case arraylength:
633 state.pop(1);
634 state.push(syms.intType);
635 break;
636 case isub:
637 case iadd:
638 case imul:
639 case idiv:
640 case imod:
641 case ishl:
642 case ishr:
643 case iushr:
644 case iand:
645 case ior:
646 case ixor:
647 state.pop(1);
648 // state.pop(1);
649 // state.push(syms.intType);
650 break;
651 case aastore:
652 state.pop(3);
653 break;
654 case land:
655 case lor:
656 case lxor:
657 case lmod:
658 case ldiv:
659 case lmul:
660 case lsub:
661 case ladd:
662 state.pop(2);
663 break;
664 case lcmp:
665 state.pop(4);
666 state.push(syms.intType);
667 break;
668 case l2i:
669 state.pop(2);
670 state.push(syms.intType);
671 break;
672 case i2l:
673 state.pop(1);
674 state.push(syms.longType);
675 break;
676 case i2f:
677 state.pop(1);
678 state.push(syms.floatType);
679 break;
680 case i2d:
681 state.pop(1);
682 state.push(syms.doubleType);
683 break;
684 case l2f:
685 state.pop(2);
686 state.push(syms.floatType);
687 break;
688 case l2d:
689 state.pop(2);
690 state.push(syms.doubleType);
691 break;
692 case f2i:
693 state.pop(1);
694 state.push(syms.intType);
695 break;
696 case f2l:
697 state.pop(1);
698 state.push(syms.longType);
699 break;
700 case f2d:
701 state.pop(1);
702 state.push(syms.doubleType);
703 break;
704 case d2i:
705 state.pop(2);
706 state.push(syms.intType);
707 break;
708 case d2l:
709 state.pop(2);
710 state.push(syms.longType);
711 break;
712 case d2f:
713 state.pop(2);
714 state.push(syms.floatType);
715 break;
716 case tableswitch:
717 case lookupswitch:
718 state.pop(1);
719 // the caller is responsible for patching up the state
720 break;
721 case dup_x1: {
722 Type val1 = state.pop1();
723 Type val2 = state.pop1();
724 state.push(val1);
725 state.push(val2);
726 state.push(val1);
727 break;
728 }
729 case bastore:
730 state.pop(3);
731 break;
732 case int2byte:
733 case int2char:
734 case int2short:
735 break;
736 case fmul:
737 case fadd:
738 case fsub:
739 case fdiv:
740 case fmod:
741 state.pop(1);
742 break;
743 case castore:
744 case iastore:
745 case fastore:
746 case sastore:
747 state.pop(3);
748 break;
749 case lastore:
750 case dastore:
751 state.pop(4);
752 break;
753 case dup2:
754 if (state.stack[state.stacksize-1] != null) {
755 Type value1 = state.pop1();
756 Type value2 = state.pop1();
757 state.push(value2);
758 state.push(value1);
759 state.push(value2);
760 state.push(value1);
761 } else {
762 Type value = state.pop2();
763 state.push(value);
764 state.push(value);
765 }
766 break;
767 case dup2_x1:
768 if (state.stack[state.stacksize-1] != null) {
769 Type value1 = state.pop1();
770 Type value2 = state.pop1();
771 Type value3 = state.pop1();
772 state.push(value2);
773 state.push(value1);
774 state.push(value3);
775 state.push(value2);
776 state.push(value1);
777 } else {
778 Type value1 = state.pop2();
779 Type value2 = state.pop1();
780 state.push(value1);
781 state.push(value2);
782 state.push(value1);
783 }
784 break;
785 case dup2_x2:
786 if (state.stack[state.stacksize-1] != null) {
787 Type value1 = state.pop1();
788 Type value2 = state.pop1();
789 if (state.stack[state.stacksize-1] != null) {
790 // form 1
791 Type value3 = state.pop1();
792 Type value4 = state.pop1();
793 state.push(value2);
794 state.push(value1);
795 state.push(value4);
796 state.push(value3);
797 state.push(value2);
798 state.push(value1);
799 } else {
800 // form 3
801 Type value3 = state.pop2();
802 state.push(value2);
803 state.push(value1);
804 state.push(value3);
805 state.push(value2);
806 state.push(value1);
807 }
808 } else {
809 Type value1 = state.pop2();
810 if (state.stack[state.stacksize-1] != null) {
811 // form 2
812 Type value2 = state.pop1();
813 Type value3 = state.pop1();
814 state.push(value1);
815 state.push(value3);
816 state.push(value2);
817 state.push(value1);
818 } else {
819 // form 4
820 Type value2 = state.pop2();
821 state.push(value1);
822 state.push(value2);
823 state.push(value1);
824 }
825 }
826 break;
827 case dup_x2: {
828 Type value1 = state.pop1();
829 if (state.stack[state.stacksize-1] != null) {
830 // form 1
831 Type value2 = state.pop1();
832 Type value3 = state.pop1();
833 state.push(value1);
834 state.push(value3);
835 state.push(value2);
836 state.push(value1);
837 } else {
838 // form 2
839 Type value2 = state.pop2();
840 state.push(value1);
841 state.push(value2);
842 state.push(value1);
843 }
844 }
845 break;
846 case fcmpl:
847 case fcmpg:
848 state.pop(2);
849 state.push(syms.intType);
850 break;
851 case dcmpl:
852 case dcmpg:
853 state.pop(4);
854 state.push(syms.intType);
855 break;
856 case swap: {
857 Type value1 = state.pop1();
858 Type value2 = state.pop1();
859 state.push(value1);
860 state.push(value2);
861 break;
862 }
863 case dadd:
864 case dsub:
865 case dmul:
866 case ddiv:
867 case dmod:
868 state.pop(2);
869 break;
870 case ret:
871 markDead();
872 break;
873 case wide:
874 // must be handled by the caller.
875 return;
876 case monitorenter:
877 case monitorexit:
878 state.pop(1);
879 break;
881 default:
882 throw new AssertionError(mnem(op));
883 }
884 postop();
885 }
887 /** Emit an opcode with a one-byte operand field.
888 */
889 public void emitop1(int op, int od) {
890 emitop(op);
891 if (!alive) return;
892 emit1(od);
893 switch (op) {
894 case bipush:
895 state.push(syms.intType);
896 break;
897 case ldc1:
898 state.push(typeForPool(pool.pool[od]));
899 break;
900 default:
901 throw new AssertionError(mnem(op));
902 }
903 postop();
904 }
906 /** The type of a constant pool entry. */
907 private Type typeForPool(Object o) {
908 if (o instanceof Integer) return syms.intType;
909 if (o instanceof Float) return syms.floatType;
910 if (o instanceof String) return syms.stringType;
911 if (o instanceof Long) return syms.longType;
912 if (o instanceof Double) return syms.doubleType;
913 if (o instanceof ClassSymbol) return syms.classType;
914 if (o instanceof Type.ArrayType) return syms.classType;
915 if (o instanceof Type.MethodType) return syms.methodTypeType;
916 if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
917 if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
918 throw new AssertionError(o);
919 }
921 /** Emit an opcode with a one-byte operand field;
922 * widen if field does not fit in a byte.
923 */
924 public void emitop1w(int op, int od) {
925 if (od > 0xFF) {
926 emitop(wide);
927 emitop(op);
928 emit2(od);
929 } else {
930 emitop(op);
931 emit1(od);
932 }
933 if (!alive) return;
934 switch (op) {
935 case iload:
936 state.push(syms.intType);
937 break;
938 case lload:
939 state.push(syms.longType);
940 break;
941 case fload:
942 state.push(syms.floatType);
943 break;
944 case dload:
945 state.push(syms.doubleType);
946 break;
947 case aload:
948 state.push(lvar[od].sym.type);
949 break;
950 case lstore:
951 case dstore:
952 state.pop(2);
953 break;
954 case istore:
955 case fstore:
956 case astore:
957 state.pop(1);
958 break;
959 case ret:
960 markDead();
961 break;
962 default:
963 throw new AssertionError(mnem(op));
964 }
965 postop();
966 }
968 /** Emit an opcode with two one-byte operand fields;
969 * widen if either field does not fit in a byte.
970 */
971 public void emitop1w(int op, int od1, int od2) {
972 if (od1 > 0xFF || od2 < -128 || od2 > 127) {
973 emitop(wide);
974 emitop(op);
975 emit2(od1);
976 emit2(od2);
977 } else {
978 emitop(op);
979 emit1(od1);
980 emit1(od2);
981 }
982 if (!alive) return;
983 switch (op) {
984 case iinc:
985 break;
986 default:
987 throw new AssertionError(mnem(op));
988 }
989 }
991 /** Emit an opcode with a two-byte operand field.
992 */
993 public void emitop2(int op, int od) {
994 emitop(op);
995 if (!alive) return;
996 emit2(od);
997 switch (op) {
998 case getstatic:
999 state.push(((Symbol)(pool.pool[od])).erasure(types));
1000 break;
1001 case putstatic:
1002 state.pop(((Symbol)(pool.pool[od])).erasure(types));
1003 break;
1004 case new_:
1005 state.push(uninitializedObject(((Symbol)(pool.pool[od])).erasure(types), cp-3));
1006 break;
1007 case sipush:
1008 state.push(syms.intType);
1009 break;
1010 case if_acmp_null:
1011 case if_acmp_nonnull:
1012 case ifeq:
1013 case ifne:
1014 case iflt:
1015 case ifge:
1016 case ifgt:
1017 case ifle:
1018 state.pop(1);
1019 break;
1020 case if_icmpeq:
1021 case if_icmpne:
1022 case if_icmplt:
1023 case if_icmpge:
1024 case if_icmpgt:
1025 case if_icmple:
1026 case if_acmpeq:
1027 case if_acmpne:
1028 state.pop(2);
1029 break;
1030 case goto_:
1031 markDead();
1032 break;
1033 case putfield:
1034 state.pop(((Symbol)(pool.pool[od])).erasure(types));
1035 state.pop(1); // object ref
1036 break;
1037 case getfield:
1038 state.pop(1); // object ref
1039 state.push(((Symbol)(pool.pool[od])).erasure(types));
1040 break;
1041 case checkcast: {
1042 state.pop(1); // object ref
1043 Object o = pool.pool[od];
1044 Type t = (o instanceof Symbol)
1045 ? ((Symbol)o).erasure(types)
1046 : types.erasure((((UniqueType)o).type));
1047 state.push(t);
1048 break; }
1049 case ldc2w:
1050 state.push(typeForPool(pool.pool[od]));
1051 break;
1052 case instanceof_:
1053 state.pop(1);
1054 state.push(syms.intType);
1055 break;
1056 case ldc2:
1057 state.push(typeForPool(pool.pool[od]));
1058 break;
1059 case jsr:
1060 break;
1061 default:
1062 throw new AssertionError(mnem(op));
1063 }
1064 // postop();
1065 }
1067 /** Emit an opcode with a four-byte operand field.
1068 */
1069 public void emitop4(int op, int od) {
1070 emitop(op);
1071 if (!alive) return;
1072 emit4(od);
1073 switch (op) {
1074 case goto_w:
1075 markDead();
1076 break;
1077 case jsr_w:
1078 break;
1079 default:
1080 throw new AssertionError(mnem(op));
1081 }
1082 // postop();
1083 }
1085 /** Align code pointer to next `incr' boundary.
1086 */
1087 public void align(int incr) {
1088 if (alive)
1089 while (cp % incr != 0) emitop0(nop);
1090 }
1092 /** Place a byte into code at address pc.
1093 * Pre: {@literal pc + 1 <= cp }.
1094 */
1095 private void put1(int pc, int op) {
1096 code[pc] = (byte)op;
1097 }
1099 /** Place two bytes into code at address pc.
1100 * Pre: {@literal pc + 2 <= cp }.
1101 */
1102 private void put2(int pc, int od) {
1103 // pre: pc + 2 <= cp
1104 put1(pc, od >> 8);
1105 put1(pc+1, od);
1106 }
1108 /** Place four bytes into code at address pc.
1109 * Pre: {@literal pc + 4 <= cp }.
1110 */
1111 public void put4(int pc, int od) {
1112 // pre: pc + 4 <= cp
1113 put1(pc , od >> 24);
1114 put1(pc+1, od >> 16);
1115 put1(pc+2, od >> 8);
1116 put1(pc+3, od);
1117 }
1119 /** Return code byte at position pc as an unsigned int.
1120 */
1121 private int get1(int pc) {
1122 return code[pc] & 0xFF;
1123 }
1125 /** Return two code bytes at position pc as an unsigned int.
1126 */
1127 private int get2(int pc) {
1128 return (get1(pc) << 8) | get1(pc+1);
1129 }
1131 /** Return four code bytes at position pc as an int.
1132 */
1133 public int get4(int pc) {
1134 // pre: pc + 4 <= cp
1135 return
1136 (get1(pc) << 24) |
1137 (get1(pc+1) << 16) |
1138 (get1(pc+2) << 8) |
1139 (get1(pc+3));
1140 }
1142 /** Is code generation currently enabled?
1143 */
1144 public boolean isAlive() {
1145 return alive || pendingJumps != null;
1146 }
1148 /** Switch code generation on/off.
1149 */
1150 public void markDead() {
1151 alive = false;
1152 }
1154 /** Declare an entry point; return current code pointer
1155 */
1156 public int entryPoint() {
1157 int pc = curPc();
1158 alive = true;
1159 pendingStackMap = needStackMap;
1160 return pc;
1161 }
1163 /** Declare an entry point with initial state;
1164 * return current code pointer
1165 */
1166 public int entryPoint(State state) {
1167 int pc = curPc();
1168 alive = true;
1169 this.state = state.dup();
1170 Assert.check(state.stacksize <= max_stack);
1171 if (debugCode) System.err.println("entry point " + state);
1172 pendingStackMap = needStackMap;
1173 return pc;
1174 }
1176 /** Declare an entry point with initial state plus a pushed value;
1177 * return current code pointer
1178 */
1179 public int entryPoint(State state, Type pushed) {
1180 int pc = curPc();
1181 alive = true;
1182 this.state = state.dup();
1183 Assert.check(state.stacksize <= max_stack);
1184 this.state.push(pushed);
1185 if (debugCode) System.err.println("entry point " + state);
1186 pendingStackMap = needStackMap;
1187 return pc;
1188 }
1191 /**************************************************************************
1192 * Stack map generation
1193 *************************************************************************/
1195 /** An entry in the stack map. */
1196 static class StackMapFrame {
1197 int pc;
1198 Type[] locals;
1199 Type[] stack;
1200 }
1202 /** A buffer of cldc stack map entries. */
1203 StackMapFrame[] stackMapBuffer = null;
1205 /** A buffer of compressed StackMapTable entries. */
1206 StackMapTableFrame[] stackMapTableBuffer = null;
1207 int stackMapBufferSize = 0;
1209 /** The last PC at which we generated a stack map. */
1210 int lastStackMapPC = -1;
1212 /** The last stack map frame in StackMapTable. */
1213 StackMapFrame lastFrame = null;
1215 /** The stack map frame before the last one. */
1216 StackMapFrame frameBeforeLast = null;
1218 /** Emit a stack map entry. */
1219 public void emitStackMap() {
1220 int pc = curPc();
1221 if (!needStackMap) return;
1225 switch (stackMap) {
1226 case CLDC:
1227 emitCLDCStackMap(pc, getLocalsSize());
1228 break;
1229 case JSR202:
1230 emitStackMapFrame(pc, getLocalsSize());
1231 break;
1232 default:
1233 throw new AssertionError("Should have chosen a stackmap format");
1234 }
1235 // DEBUG code follows
1236 if (debugCode) state.dump(pc);
1237 }
1239 private int getLocalsSize() {
1240 int nextLocal = 0;
1241 for (int i=max_locals-1; i>=0; i--) {
1242 if (state.defined.isMember(i) && lvar[i] != null) {
1243 nextLocal = i + width(lvar[i].sym.erasure(types));
1244 break;
1245 }
1246 }
1247 return nextLocal;
1248 }
1250 /** Emit a CLDC stack map frame. */
1251 void emitCLDCStackMap(int pc, int localsSize) {
1252 if (lastStackMapPC == pc) {
1253 // drop existing stackmap at this offset
1254 stackMapBuffer[--stackMapBufferSize] = null;
1255 }
1256 lastStackMapPC = pc;
1258 if (stackMapBuffer == null) {
1259 stackMapBuffer = new StackMapFrame[20];
1260 } else {
1261 stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize);
1262 }
1263 StackMapFrame frame =
1264 stackMapBuffer[stackMapBufferSize++] = new StackMapFrame();
1265 frame.pc = pc;
1267 frame.locals = new Type[localsSize];
1268 for (int i=0; i<localsSize; i++) {
1269 if (state.defined.isMember(i) && lvar[i] != null) {
1270 Type vtype = lvar[i].sym.type;
1271 if (!(vtype instanceof UninitializedType))
1272 vtype = types.erasure(vtype);
1273 frame.locals[i] = vtype;
1274 }
1275 }
1276 frame.stack = new Type[state.stacksize];
1277 for (int i=0; i<state.stacksize; i++)
1278 frame.stack[i] = state.stack[i];
1279 }
1281 void emitStackMapFrame(int pc, int localsSize) {
1282 if (lastFrame == null) {
1283 // first frame
1284 lastFrame = getInitialFrame();
1285 } else if (lastFrame.pc == pc) {
1286 // drop existing stackmap at this offset
1287 stackMapTableBuffer[--stackMapBufferSize] = null;
1288 lastFrame = frameBeforeLast;
1289 frameBeforeLast = null;
1290 }
1292 StackMapFrame frame = new StackMapFrame();
1293 frame.pc = pc;
1295 int localCount = 0;
1296 Type[] locals = new Type[localsSize];
1297 for (int i=0; i<localsSize; i++, localCount++) {
1298 if (state.defined.isMember(i) && lvar[i] != null) {
1299 Type vtype = lvar[i].sym.type;
1300 if (!(vtype instanceof UninitializedType))
1301 vtype = types.erasure(vtype);
1302 locals[i] = vtype;
1303 if (width(vtype) > 1) i++;
1304 }
1305 }
1306 frame.locals = new Type[localCount];
1307 for (int i=0, j=0; i<localsSize; i++, j++) {
1308 Assert.check(j < localCount);
1309 frame.locals[j] = locals[i];
1310 if (width(locals[i]) > 1) i++;
1311 }
1313 int stackCount = 0;
1314 for (int i=0; i<state.stacksize; i++) {
1315 if (state.stack[i] != null) {
1316 stackCount++;
1317 }
1318 }
1319 frame.stack = new Type[stackCount];
1320 stackCount = 0;
1321 for (int i=0; i<state.stacksize; i++) {
1322 if (state.stack[i] != null) {
1323 frame.stack[stackCount++] = types.erasure(state.stack[i]);
1324 }
1325 }
1327 if (stackMapTableBuffer == null) {
1328 stackMapTableBuffer = new StackMapTableFrame[20];
1329 } else {
1330 stackMapTableBuffer = ArrayUtils.ensureCapacity(
1331 stackMapTableBuffer,
1332 stackMapBufferSize);
1333 }
1334 stackMapTableBuffer[stackMapBufferSize++] =
1335 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
1337 frameBeforeLast = lastFrame;
1338 lastFrame = frame;
1339 }
1341 StackMapFrame getInitialFrame() {
1342 StackMapFrame frame = new StackMapFrame();
1343 List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes;
1344 int len = arg_types.length();
1345 int count = 0;
1346 if (!meth.isStatic()) {
1347 Type thisType = meth.owner.type;
1348 frame.locals = new Type[len+1];
1349 if (meth.isConstructor() && thisType != syms.objectType) {
1350 frame.locals[count++] = UninitializedType.uninitializedThis(thisType);
1351 } else {
1352 frame.locals[count++] = types.erasure(thisType);
1353 }
1354 } else {
1355 frame.locals = new Type[len];
1356 }
1357 for (Type arg_type : arg_types) {
1358 frame.locals[count++] = types.erasure(arg_type);
1359 }
1360 frame.pc = -1;
1361 frame.stack = null;
1362 return frame;
1363 }
1366 /**************************************************************************
1367 * Operations having to do with jumps
1368 *************************************************************************/
1370 /** A chain represents a list of unresolved jumps. Jump locations
1371 * are sorted in decreasing order.
1372 */
1373 public static class Chain {
1375 /** The position of the jump instruction.
1376 */
1377 public final int pc;
1379 /** The machine state after the jump instruction.
1380 * Invariant: all elements of a chain list have the same stacksize
1381 * and compatible stack and register contents.
1382 */
1383 Code.State state;
1385 /** The next jump in the list.
1386 */
1387 public final Chain next;
1389 /** Construct a chain from its jump position, stacksize, previous
1390 * chain, and machine state.
1391 */
1392 public Chain(int pc, Chain next, Code.State state) {
1393 this.pc = pc;
1394 this.next = next;
1395 this.state = state;
1396 }
1397 }
1399 /** Negate a branch opcode.
1400 */
1401 public static int negate(int opcode) {
1402 if (opcode == if_acmp_null) return if_acmp_nonnull;
1403 else if (opcode == if_acmp_nonnull) return if_acmp_null;
1404 else return ((opcode + 1) ^ 1) - 1;
1405 }
1407 /** Emit a jump instruction.
1408 * Return code pointer of instruction to be patched.
1409 */
1410 public int emitJump(int opcode) {
1411 if (fatcode) {
1412 if (opcode == goto_ || opcode == jsr) {
1413 emitop4(opcode + goto_w - goto_, 0);
1414 } else {
1415 emitop2(negate(opcode), 8);
1416 emitop4(goto_w, 0);
1417 alive = true;
1418 pendingStackMap = needStackMap;
1419 }
1420 return cp - 5;
1421 } else {
1422 emitop2(opcode, 0);
1423 return cp - 3;
1424 }
1425 }
1427 /** Emit a branch with given opcode; return its chain.
1428 * branch differs from jump in that jsr is treated as no-op.
1429 */
1430 public Chain branch(int opcode) {
1431 Chain result = null;
1432 if (opcode == goto_) {
1433 result = pendingJumps;
1434 pendingJumps = null;
1435 }
1436 if (opcode != dontgoto && isAlive()) {
1437 result = new Chain(emitJump(opcode),
1438 result,
1439 state.dup());
1440 fixedPc = fatcode;
1441 if (opcode == goto_) alive = false;
1442 }
1443 return result;
1444 }
1446 /** Resolve chain to point to given target.
1447 */
1448 public void resolve(Chain chain, int target) {
1449 boolean changed = false;
1450 State newState = state;
1451 for (; chain != null; chain = chain.next) {
1452 Assert.check(state != chain.state
1453 && (target > chain.pc || state.stacksize == 0));
1454 if (target >= cp) {
1455 target = cp;
1456 } else if (get1(target) == goto_) {
1457 if (fatcode) target = target + get4(target + 1);
1458 else target = target + get2(target + 1);
1459 }
1460 if (get1(chain.pc) == goto_ &&
1461 chain.pc + 3 == target && target == cp && !fixedPc) {
1462 // If goto the next instruction, the jump is not needed:
1463 // compact the code.
1464 cp = cp - 3;
1465 target = target - 3;
1466 if (chain.next == null) {
1467 // This is the only jump to the target. Exit the loop
1468 // without setting new state. The code is reachable
1469 // from the instruction before goto_.
1470 alive = true;
1471 break;
1472 }
1473 } else {
1474 if (fatcode)
1475 put4(chain.pc + 1, target - chain.pc);
1476 else if (target - chain.pc < Short.MIN_VALUE ||
1477 target - chain.pc > Short.MAX_VALUE)
1478 fatcode = true;
1479 else
1480 put2(chain.pc + 1, target - chain.pc);
1481 Assert.check(!alive ||
1482 chain.state.stacksize == newState.stacksize &&
1483 chain.state.nlocks == newState.nlocks);
1484 }
1485 fixedPc = true;
1486 if (cp == target) {
1487 changed = true;
1488 if (debugCode)
1489 System.err.println("resolving chain state=" + chain.state);
1490 if (alive) {
1491 newState = chain.state.join(newState);
1492 } else {
1493 newState = chain.state;
1494 alive = true;
1495 }
1496 }
1497 }
1498 Assert.check(!changed || state != newState);
1499 if (state != newState) {
1500 setDefined(newState.defined);
1501 state = newState;
1502 pendingStackMap = needStackMap;
1503 }
1504 }
1506 /** Resolve chain to point to current code pointer.
1507 */
1508 public void resolve(Chain chain) {
1509 Assert.check(
1510 !alive ||
1511 chain==null ||
1512 state.stacksize == chain.state.stacksize &&
1513 state.nlocks == chain.state.nlocks);
1514 pendingJumps = mergeChains(chain, pendingJumps);
1515 }
1517 /** Resolve any pending jumps.
1518 */
1519 public void resolvePending() {
1520 Chain x = pendingJumps;
1521 pendingJumps = null;
1522 resolve(x, cp);
1523 }
1525 /** Merge the jumps in of two chains into one.
1526 */
1527 public static Chain mergeChains(Chain chain1, Chain chain2) {
1528 // recursive merge sort
1529 if (chain2 == null) return chain1;
1530 if (chain1 == null) return chain2;
1531 Assert.check(
1532 chain1.state.stacksize == chain2.state.stacksize &&
1533 chain1.state.nlocks == chain2.state.nlocks);
1534 if (chain1.pc < chain2.pc)
1535 return new Chain(
1536 chain2.pc,
1537 mergeChains(chain1, chain2.next),
1538 chain2.state);
1539 return new Chain(
1540 chain1.pc,
1541 mergeChains(chain1.next, chain2),
1542 chain1.state);
1543 }
1546 /* **************************************************************************
1547 * Catch clauses
1548 ****************************************************************************/
1550 /** Add a catch clause to code.
1551 */
1552 public void addCatch(
1553 char startPc, char endPc, char handlerPc, char catchType) {
1554 catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType});
1555 }
1558 public void compressCatchTable() {
1559 ListBuffer<char[]> compressedCatchInfo = ListBuffer.lb();
1560 List<Integer> handlerPcs = List.nil();
1561 for (char[] catchEntry : catchInfo) {
1562 handlerPcs = handlerPcs.prepend((int)catchEntry[2]);
1563 }
1564 for (char[] catchEntry : catchInfo) {
1565 int startpc = catchEntry[0];
1566 int endpc = catchEntry[1];
1567 if (startpc == endpc ||
1568 (startpc == (endpc - 1) &&
1569 handlerPcs.contains(startpc))) {
1570 continue;
1571 } else {
1572 compressedCatchInfo.append(catchEntry);
1573 }
1574 }
1575 catchInfo = compressedCatchInfo;
1576 }
1579 /* **************************************************************************
1580 * Line numbers
1581 ****************************************************************************/
1583 /** Add a line number entry.
1584 */
1585 public void addLineNumber(char startPc, char lineNumber) {
1586 if (lineDebugInfo) {
1587 if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc)
1588 lineInfo = lineInfo.tail;
1589 if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber)
1590 lineInfo = lineInfo.prepend(new char[]{startPc, lineNumber});
1591 }
1592 }
1594 /** Mark beginning of statement.
1595 */
1596 public void statBegin(int pos) {
1597 if (pos != Position.NOPOS) {
1598 pendingStatPos = pos;
1599 }
1600 }
1602 /** Force stat begin eagerly
1603 */
1604 public void markStatBegin() {
1605 if (alive && lineDebugInfo) {
1606 int line = lineMap.getLineNumber(pendingStatPos);
1607 char cp1 = (char)cp;
1608 char line1 = (char)line;
1609 if (cp1 == cp && line1 == line)
1610 addLineNumber(cp1, line1);
1611 }
1612 pendingStatPos = Position.NOPOS;
1613 }
1616 /* **************************************************************************
1617 * Simulated VM machine state
1618 ****************************************************************************/
1620 class State implements Cloneable {
1621 /** The set of registers containing values. */
1622 Bits defined;
1624 /** The (types of the) contents of the machine stack. */
1625 Type[] stack;
1627 /** The first stack position currently unused. */
1628 int stacksize;
1630 /** The numbers of registers containing locked monitors. */
1631 int[] locks;
1632 int nlocks;
1634 State() {
1635 defined = new Bits();
1636 stack = new Type[16];
1637 }
1639 State dup() {
1640 try {
1641 State state = (State)super.clone();
1642 state.defined = defined.dup();
1643 state.stack = stack.clone();
1644 if (locks != null) state.locks = locks.clone();
1645 if (debugCode) {
1646 System.err.println("duping state " + this);
1647 dump();
1648 }
1649 return state;
1650 } catch (CloneNotSupportedException ex) {
1651 throw new AssertionError(ex);
1652 }
1653 }
1655 void lock(int register) {
1656 if (locks == null) {
1657 locks = new int[20];
1658 } else {
1659 locks = ArrayUtils.ensureCapacity(locks, nlocks);
1660 }
1661 locks[nlocks] = register;
1662 nlocks++;
1663 }
1665 void unlock(int register) {
1666 nlocks--;
1667 Assert.check(locks[nlocks] == register);
1668 locks[nlocks] = -1;
1669 }
1671 void push(Type t) {
1672 if (debugCode) System.err.println(" pushing " + t);
1673 switch (t.getTag()) {
1674 case VOID:
1675 return;
1676 case BYTE:
1677 case CHAR:
1678 case SHORT:
1679 case BOOLEAN:
1680 t = syms.intType;
1681 break;
1682 default:
1683 break;
1684 }
1685 stack = ArrayUtils.ensureCapacity(stack, stacksize+2);
1686 stack[stacksize++] = t;
1687 switch (width(t)) {
1688 case 1:
1689 break;
1690 case 2:
1691 stack[stacksize++] = null;
1692 break;
1693 default:
1694 throw new AssertionError(t);
1695 }
1696 if (stacksize > max_stack)
1697 max_stack = stacksize;
1698 }
1700 Type pop1() {
1701 if (debugCode) System.err.println(" popping " + 1);
1702 stacksize--;
1703 Type result = stack[stacksize];
1704 stack[stacksize] = null;
1705 Assert.check(result != null && width(result) == 1);
1706 return result;
1707 }
1709 Type peek() {
1710 return stack[stacksize-1];
1711 }
1713 Type pop2() {
1714 if (debugCode) System.err.println(" popping " + 2);
1715 stacksize -= 2;
1716 Type result = stack[stacksize];
1717 stack[stacksize] = null;
1718 Assert.check(stack[stacksize+1] == null
1719 && result != null && width(result) == 2);
1720 return result;
1721 }
1723 void pop(int n) {
1724 if (debugCode) System.err.println(" popping " + n);
1725 while (n > 0) {
1726 stack[--stacksize] = null;
1727 n--;
1728 }
1729 }
1731 void pop(Type t) {
1732 pop(width(t));
1733 }
1735 /** Force the top of the stack to be treated as this supertype
1736 * of its current type. */
1737 void forceStackTop(Type t) {
1738 if (!alive) return;
1739 switch (t.getTag()) {
1740 case CLASS:
1741 case ARRAY:
1742 int width = width(t);
1743 Type old = stack[stacksize-width];
1744 Assert.check(types.isSubtype(types.erasure(old),
1745 types.erasure(t)));
1746 stack[stacksize-width] = t;
1747 break;
1748 default:
1749 }
1750 }
1752 void markInitialized(UninitializedType old) {
1753 Type newtype = old.initializedType();
1754 for (int i=0; i<stacksize; i++)
1755 if (stack[i] == old) stack[i] = newtype;
1756 for (int i=0; i<lvar.length; i++) {
1757 LocalVar lv = lvar[i];
1758 if (lv != null && lv.sym.type == old) {
1759 VarSymbol sym = lv.sym;
1760 sym = sym.clone(sym.owner);
1761 sym.type = newtype;
1762 LocalVar newlv = lvar[i] = new LocalVar(sym);
1763 // should the following be initialized to cp?
1764 newlv.start_pc = lv.start_pc;
1765 }
1766 }
1767 }
1769 State join(State other) {
1770 defined = defined.andSet(other.defined);
1771 Assert.check(stacksize == other.stacksize
1772 && nlocks == other.nlocks);
1773 for (int i=0; i<stacksize; ) {
1774 Type t = stack[i];
1775 Type tother = other.stack[i];
1776 Type result =
1777 t==tother ? t :
1778 types.isSubtype(t, tother) ? tother :
1779 types.isSubtype(tother, t) ? t :
1780 error();
1781 int w = width(result);
1782 stack[i] = result;
1783 if (w == 2) Assert.checkNull(stack[i+1]);
1784 i += w;
1785 }
1786 return this;
1787 }
1789 Type error() {
1790 throw new AssertionError("inconsistent stack types at join point");
1791 }
1793 void dump() {
1794 dump(-1);
1795 }
1797 void dump(int pc) {
1798 System.err.print("stackMap for " + meth.owner + "." + meth);
1799 if (pc == -1)
1800 System.out.println();
1801 else
1802 System.out.println(" at " + pc);
1803 System.err.println(" stack (from bottom):");
1804 for (int i=0; i<stacksize; i++)
1805 System.err.println(" " + i + ": " + stack[i]);
1807 int lastLocal = 0;
1808 for (int i=max_locals-1; i>=0; i--) {
1809 if (defined.isMember(i)) {
1810 lastLocal = i;
1811 break;
1812 }
1813 }
1814 if (lastLocal >= 0)
1815 System.err.println(" locals:");
1816 for (int i=0; i<=lastLocal; i++) {
1817 System.err.print(" " + i + ": ");
1818 if (defined.isMember(i)) {
1819 LocalVar var = lvar[i];
1820 if (var == null) {
1821 System.err.println("(none)");
1822 } else if (var.sym == null)
1823 System.err.println("UNKNOWN!");
1824 else
1825 System.err.println("" + var.sym + " of type " +
1826 var.sym.erasure(types));
1827 } else {
1828 System.err.println("undefined");
1829 }
1830 }
1831 if (nlocks != 0) {
1832 System.err.print(" locks:");
1833 for (int i=0; i<nlocks; i++) {
1834 System.err.print(" " + locks[i]);
1835 }
1836 System.err.println();
1837 }
1838 }
1839 }
1841 static final Type jsrReturnValue = new Type(INT, null);
1844 /* **************************************************************************
1845 * Local variables
1846 ****************************************************************************/
1848 /** A live range of a local variable. */
1849 static class LocalVar {
1850 final VarSymbol sym;
1851 final char reg;
1852 char start_pc = Character.MAX_VALUE;
1853 char length = Character.MAX_VALUE;
1854 LocalVar(VarSymbol v) {
1855 this.sym = v;
1856 this.reg = (char)v.adr;
1857 }
1858 public LocalVar dup() {
1859 return new LocalVar(sym);
1860 }
1861 public String toString() {
1862 return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length);
1863 }
1864 };
1866 /** Local variables, indexed by register. */
1867 LocalVar[] lvar;
1869 /** Add a new local variable. */
1870 private void addLocalVar(VarSymbol v) {
1871 int adr = v.adr;
1872 lvar = ArrayUtils.ensureCapacity(lvar, adr+1);
1873 Assert.checkNull(lvar[adr]);
1874 if (pendingJumps != null) resolvePending();
1875 lvar[adr] = new LocalVar(v);
1876 state.defined.excl(adr);
1877 }
1879 /** Set the current variable defined state. */
1880 public void setDefined(Bits newDefined) {
1881 if (alive && newDefined != state.defined) {
1882 Bits diff = state.defined.dup().xorSet(newDefined);
1883 for (int adr = diff.nextBit(0);
1884 adr >= 0;
1885 adr = diff.nextBit(adr+1)) {
1886 if (adr >= nextreg)
1887 state.defined.excl(adr);
1888 else if (state.defined.isMember(adr))
1889 setUndefined(adr);
1890 else
1891 setDefined(adr);
1892 }
1893 }
1894 }
1896 /** Mark a register as being (possibly) defined. */
1897 public void setDefined(int adr) {
1898 LocalVar v = lvar[adr];
1899 if (v == null) {
1900 state.defined.excl(adr);
1901 } else {
1902 state.defined.incl(adr);
1903 if (cp < Character.MAX_VALUE) {
1904 if (v.start_pc == Character.MAX_VALUE)
1905 v.start_pc = (char)cp;
1906 }
1907 }
1908 }
1910 /** Mark a register as being undefined. */
1911 public void setUndefined(int adr) {
1912 state.defined.excl(adr);
1913 if (adr < lvar.length &&
1914 lvar[adr] != null &&
1915 lvar[adr].start_pc != Character.MAX_VALUE) {
1916 LocalVar v = lvar[adr];
1917 char length = (char)(curPc() - v.start_pc);
1918 if (length > 0 && length < Character.MAX_VALUE) {
1919 lvar[adr] = v.dup();
1920 v.length = length;
1921 putVar(v);
1922 } else {
1923 v.start_pc = Character.MAX_VALUE;
1924 }
1925 }
1926 }
1928 /** End the scope of a variable. */
1929 private void endScope(int adr) {
1930 LocalVar v = lvar[adr];
1931 if (v != null) {
1932 lvar[adr] = null;
1933 if (v.start_pc != Character.MAX_VALUE) {
1934 char length = (char)(curPc() - v.start_pc);
1935 if (length < Character.MAX_VALUE) {
1936 v.length = length;
1937 putVar(v);
1938 fillLocalVarPosition(v);
1939 }
1940 }
1941 }
1942 state.defined.excl(adr);
1943 }
1945 private void fillLocalVarPosition(LocalVar lv) {
1946 if (lv == null || lv.sym == null
1947 || lv.sym.annotations.isTypesEmpty())
1948 return;
1949 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
1950 TypeAnnotationPosition p = ta.position;
1951 p.lvarOffset = new int[] { (int)lv.start_pc };
1952 p.lvarLength = new int[] { (int)lv.length };
1953 p.lvarIndex = new int[] { (int)lv.reg };
1954 p.isValidOffset = true;
1955 }
1956 }
1958 // Method to be called after compressCatchTable to
1959 // fill in the exception table index for type
1960 // annotations on exception parameters.
1961 public void fillExceptionParameterPositions() {
1962 for (int i = 0; i < varBufferSize; ++i) {
1963 LocalVar lv = varBuffer[i];
1964 if (lv == null || lv.sym == null
1965 || lv.sym.annotations.isTypesEmpty()
1966 || !lv.sym.isExceptionParameter())
1967 return;
1969 int exidx = findExceptionIndex(lv);
1971 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
1972 TypeAnnotationPosition p = ta.position;
1973 p.exception_index = exidx;
1974 }
1975 }
1976 }
1978 private int findExceptionIndex(LocalVar lv) {
1979 List<char[]> iter = catchInfo.toList();
1980 int len = catchInfo.length();
1981 for (int i = 0; i < len; ++i) {
1982 char[] catchEntry = iter.head;
1983 iter = iter.tail;
1984 char handlerpc = catchEntry[2];
1985 if (lv.start_pc == handlerpc + 1) {
1986 return i;
1987 }
1988 }
1989 return -1;
1990 }
1992 /** Put a live variable range into the buffer to be output to the
1993 * class file.
1994 */
1995 void putVar(LocalVar var) {
1996 // Keep local variables if
1997 // 1) we need them for debug information
1998 // 2) it is an exception type and it contains type annotations
1999 if (!varDebugInfo &&
2000 (!var.sym.isExceptionParameter() ||
2001 var.sym.annotations.isTypesEmpty())) return;
2002 if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
2003 if (varBuffer == null)
2004 varBuffer = new LocalVar[20];
2005 else
2006 varBuffer = ArrayUtils.ensureCapacity(varBuffer, varBufferSize);
2007 varBuffer[varBufferSize++] = var;
2008 }
2010 /** Previously live local variables, to be put into the variable table. */
2011 LocalVar[] varBuffer;
2012 int varBufferSize;
2014 /** Create a new local variable address and return it.
2015 */
2016 private int newLocal(int typecode) {
2017 int reg = nextreg;
2018 int w = width(typecode);
2019 nextreg = reg + w;
2020 if (nextreg > max_locals) max_locals = nextreg;
2021 return reg;
2022 }
2024 private int newLocal(Type type) {
2025 return newLocal(typecode(type));
2026 }
2028 public int newLocal(VarSymbol v) {
2029 int reg = v.adr = newLocal(v.erasure(types));
2030 addLocalVar(v);
2031 return reg;
2032 }
2034 /** Start a set of fresh registers.
2035 */
2036 public void newRegSegment() {
2037 nextreg = max_locals;
2038 }
2040 /** End scopes of all variables with registers ≥ first.
2041 */
2042 public void endScopes(int first) {
2043 int prevNextReg = nextreg;
2044 nextreg = first;
2045 for (int i = nextreg; i < prevNextReg; i++) endScope(i);
2046 }
2048 /**************************************************************************
2049 * static tables
2050 *************************************************************************/
2052 public static String mnem(int opcode) {
2053 return Mneumonics.mnem[opcode];
2054 }
2056 private static class Mneumonics {
2057 private final static String[] mnem = new String[ByteCodeCount];
2058 static {
2059 mnem[nop] = "nop";
2060 mnem[aconst_null] = "aconst_null";
2061 mnem[iconst_m1] = "iconst_m1";
2062 mnem[iconst_0] = "iconst_0";
2063 mnem[iconst_1] = "iconst_1";
2064 mnem[iconst_2] = "iconst_2";
2065 mnem[iconst_3] = "iconst_3";
2066 mnem[iconst_4] = "iconst_4";
2067 mnem[iconst_5] = "iconst_5";
2068 mnem[lconst_0] = "lconst_0";
2069 mnem[lconst_1] = "lconst_1";
2070 mnem[fconst_0] = "fconst_0";
2071 mnem[fconst_1] = "fconst_1";
2072 mnem[fconst_2] = "fconst_2";
2073 mnem[dconst_0] = "dconst_0";
2074 mnem[dconst_1] = "dconst_1";
2075 mnem[bipush] = "bipush";
2076 mnem[sipush] = "sipush";
2077 mnem[ldc1] = "ldc1";
2078 mnem[ldc2] = "ldc2";
2079 mnem[ldc2w] = "ldc2w";
2080 mnem[iload] = "iload";
2081 mnem[lload] = "lload";
2082 mnem[fload] = "fload";
2083 mnem[dload] = "dload";
2084 mnem[aload] = "aload";
2085 mnem[iload_0] = "iload_0";
2086 mnem[lload_0] = "lload_0";
2087 mnem[fload_0] = "fload_0";
2088 mnem[dload_0] = "dload_0";
2089 mnem[aload_0] = "aload_0";
2090 mnem[iload_1] = "iload_1";
2091 mnem[lload_1] = "lload_1";
2092 mnem[fload_1] = "fload_1";
2093 mnem[dload_1] = "dload_1";
2094 mnem[aload_1] = "aload_1";
2095 mnem[iload_2] = "iload_2";
2096 mnem[lload_2] = "lload_2";
2097 mnem[fload_2] = "fload_2";
2098 mnem[dload_2] = "dload_2";
2099 mnem[aload_2] = "aload_2";
2100 mnem[iload_3] = "iload_3";
2101 mnem[lload_3] = "lload_3";
2102 mnem[fload_3] = "fload_3";
2103 mnem[dload_3] = "dload_3";
2104 mnem[aload_3] = "aload_3";
2105 mnem[iaload] = "iaload";
2106 mnem[laload] = "laload";
2107 mnem[faload] = "faload";
2108 mnem[daload] = "daload";
2109 mnem[aaload] = "aaload";
2110 mnem[baload] = "baload";
2111 mnem[caload] = "caload";
2112 mnem[saload] = "saload";
2113 mnem[istore] = "istore";
2114 mnem[lstore] = "lstore";
2115 mnem[fstore] = "fstore";
2116 mnem[dstore] = "dstore";
2117 mnem[astore] = "astore";
2118 mnem[istore_0] = "istore_0";
2119 mnem[lstore_0] = "lstore_0";
2120 mnem[fstore_0] = "fstore_0";
2121 mnem[dstore_0] = "dstore_0";
2122 mnem[astore_0] = "astore_0";
2123 mnem[istore_1] = "istore_1";
2124 mnem[lstore_1] = "lstore_1";
2125 mnem[fstore_1] = "fstore_1";
2126 mnem[dstore_1] = "dstore_1";
2127 mnem[astore_1] = "astore_1";
2128 mnem[istore_2] = "istore_2";
2129 mnem[lstore_2] = "lstore_2";
2130 mnem[fstore_2] = "fstore_2";
2131 mnem[dstore_2] = "dstore_2";
2132 mnem[astore_2] = "astore_2";
2133 mnem[istore_3] = "istore_3";
2134 mnem[lstore_3] = "lstore_3";
2135 mnem[fstore_3] = "fstore_3";
2136 mnem[dstore_3] = "dstore_3";
2137 mnem[astore_3] = "astore_3";
2138 mnem[iastore] = "iastore";
2139 mnem[lastore] = "lastore";
2140 mnem[fastore] = "fastore";
2141 mnem[dastore] = "dastore";
2142 mnem[aastore] = "aastore";
2143 mnem[bastore] = "bastore";
2144 mnem[castore] = "castore";
2145 mnem[sastore] = "sastore";
2146 mnem[pop] = "pop";
2147 mnem[pop2] = "pop2";
2148 mnem[dup] = "dup";
2149 mnem[dup_x1] = "dup_x1";
2150 mnem[dup_x2] = "dup_x2";
2151 mnem[dup2] = "dup2";
2152 mnem[dup2_x1] = "dup2_x1";
2153 mnem[dup2_x2] = "dup2_x2";
2154 mnem[swap] = "swap";
2155 mnem[iadd] = "iadd";
2156 mnem[ladd] = "ladd";
2157 mnem[fadd] = "fadd";
2158 mnem[dadd] = "dadd";
2159 mnem[isub] = "isub";
2160 mnem[lsub] = "lsub";
2161 mnem[fsub] = "fsub";
2162 mnem[dsub] = "dsub";
2163 mnem[imul] = "imul";
2164 mnem[lmul] = "lmul";
2165 mnem[fmul] = "fmul";
2166 mnem[dmul] = "dmul";
2167 mnem[idiv] = "idiv";
2168 mnem[ldiv] = "ldiv";
2169 mnem[fdiv] = "fdiv";
2170 mnem[ddiv] = "ddiv";
2171 mnem[imod] = "imod";
2172 mnem[lmod] = "lmod";
2173 mnem[fmod] = "fmod";
2174 mnem[dmod] = "dmod";
2175 mnem[ineg] = "ineg";
2176 mnem[lneg] = "lneg";
2177 mnem[fneg] = "fneg";
2178 mnem[dneg] = "dneg";
2179 mnem[ishl] = "ishl";
2180 mnem[lshl] = "lshl";
2181 mnem[ishr] = "ishr";
2182 mnem[lshr] = "lshr";
2183 mnem[iushr] = "iushr";
2184 mnem[lushr] = "lushr";
2185 mnem[iand] = "iand";
2186 mnem[land] = "land";
2187 mnem[ior] = "ior";
2188 mnem[lor] = "lor";
2189 mnem[ixor] = "ixor";
2190 mnem[lxor] = "lxor";
2191 mnem[iinc] = "iinc";
2192 mnem[i2l] = "i2l";
2193 mnem[i2f] = "i2f";
2194 mnem[i2d] = "i2d";
2195 mnem[l2i] = "l2i";
2196 mnem[l2f] = "l2f";
2197 mnem[l2d] = "l2d";
2198 mnem[f2i] = "f2i";
2199 mnem[f2l] = "f2l";
2200 mnem[f2d] = "f2d";
2201 mnem[d2i] = "d2i";
2202 mnem[d2l] = "d2l";
2203 mnem[d2f] = "d2f";
2204 mnem[int2byte] = "int2byte";
2205 mnem[int2char] = "int2char";
2206 mnem[int2short] = "int2short";
2207 mnem[lcmp] = "lcmp";
2208 mnem[fcmpl] = "fcmpl";
2209 mnem[fcmpg] = "fcmpg";
2210 mnem[dcmpl] = "dcmpl";
2211 mnem[dcmpg] = "dcmpg";
2212 mnem[ifeq] = "ifeq";
2213 mnem[ifne] = "ifne";
2214 mnem[iflt] = "iflt";
2215 mnem[ifge] = "ifge";
2216 mnem[ifgt] = "ifgt";
2217 mnem[ifle] = "ifle";
2218 mnem[if_icmpeq] = "if_icmpeq";
2219 mnem[if_icmpne] = "if_icmpne";
2220 mnem[if_icmplt] = "if_icmplt";
2221 mnem[if_icmpge] = "if_icmpge";
2222 mnem[if_icmpgt] = "if_icmpgt";
2223 mnem[if_icmple] = "if_icmple";
2224 mnem[if_acmpeq] = "if_acmpeq";
2225 mnem[if_acmpne] = "if_acmpne";
2226 mnem[goto_] = "goto_";
2227 mnem[jsr] = "jsr";
2228 mnem[ret] = "ret";
2229 mnem[tableswitch] = "tableswitch";
2230 mnem[lookupswitch] = "lookupswitch";
2231 mnem[ireturn] = "ireturn";
2232 mnem[lreturn] = "lreturn";
2233 mnem[freturn] = "freturn";
2234 mnem[dreturn] = "dreturn";
2235 mnem[areturn] = "areturn";
2236 mnem[return_] = "return_";
2237 mnem[getstatic] = "getstatic";
2238 mnem[putstatic] = "putstatic";
2239 mnem[getfield] = "getfield";
2240 mnem[putfield] = "putfield";
2241 mnem[invokevirtual] = "invokevirtual";
2242 mnem[invokespecial] = "invokespecial";
2243 mnem[invokestatic] = "invokestatic";
2244 mnem[invokeinterface] = "invokeinterface";
2245 mnem[invokedynamic] = "invokedynamic";
2246 mnem[new_] = "new_";
2247 mnem[newarray] = "newarray";
2248 mnem[anewarray] = "anewarray";
2249 mnem[arraylength] = "arraylength";
2250 mnem[athrow] = "athrow";
2251 mnem[checkcast] = "checkcast";
2252 mnem[instanceof_] = "instanceof_";
2253 mnem[monitorenter] = "monitorenter";
2254 mnem[monitorexit] = "monitorexit";
2255 mnem[wide] = "wide";
2256 mnem[multianewarray] = "multianewarray";
2257 mnem[if_acmp_null] = "if_acmp_null";
2258 mnem[if_acmp_nonnull] = "if_acmp_nonnull";
2259 mnem[goto_w] = "goto_w";
2260 mnem[jsr_w] = "jsr_w";
2261 mnem[breakpoint] = "breakpoint";
2262 }
2263 }
2264 }