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