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